Grunt只关注更改文件

时间:2014-04-01 12:00:08

标签: gruntjs grunt-contrib-watch

我希望有一个包含2个任务的gruntfile:less(编译所有较少的文件)和watch(监听更改并重新编译已更改的文件)。

我有以下Gruntfile.js:

module.exports = function(grunt) {
    var files = [
        {
            expand: true,
            cwd: 'media/less',
            src: ['*.less'],
            dest: 'media/css/',
            ext: '.css'
        },
        {
            expand: true,
            cwd: 'media/less/vendor',
            src: ['*.less'],
            dest: 'media/css/vendor/',
            ext: '.css'
        },
        {
            expand: true,
            cwd: 'media/admin/less',
            src: ['*.less'],
            dest: 'media/admin/css/',
            ext: '.css'
        }
    ];

    grunt.initConfig({
        less: {
            development: {
                options: {
                    compress: false,
                    yuicompress: true,
                    optimization: 2
                },
                files: files
            },
            production: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: files
            }
        },
        watch: {
            styles: {
                files: ['media/**/*.less'],
                tasks: ['less:development'],
                options: {
                    nospawn: true
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['less:development']);
};

less任务正确运行,没有任何问题。但是watch任务会监听更改,但在更改一个文件时会重新编译所有文件。我怀疑它与我如何设置less任务有关,因为我希望我的文件列表更少动态,而不是手动添加每个文件。

根据this answer grunt应该已经支持了这一点,但我不确定如何。

2 个答案:

答案 0 :(得分:1)

使用watch事件结束并覆盖files任务的less属性。这是我的最终代码:

module.exports = function(grunt) {
    var files = [
        {
            expand: true,
            cwd: 'media/less',
            src: ['*.less'],
            dest: 'media/css/',
            ext: '.css',
            extDot: 'last'
        },
        {
            expand: true,
            cwd: 'media/less/vendor',
            src: ['*.less'],
            dest: 'media/css/vendor/',
            ext: '.css',
            extDot: 'last'
        },
        {
            expand: true,
            cwd: 'media/admin/less',
            src: ['*.less'],
            dest: 'media/admin/css/',
            ext: '.css',
            extDot: 'last'
        }
    ];

    grunt.initConfig({
        less: {
            development: {
                options: {
                    compress: false,
                    yuicompress: true,
                    optimization: 2
                },
                files: files
            },
            production: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: files
            }
        },
        watch: {
            styles: {
                files: ['media/**/*.less'],
                tasks: ['less:development'],
                options: {
                    nospawn: true
                }
            }
        }
    });

    grunt.event.on('watch', function(action, filepath){
        // ignore include files, TODO: have naming convention
        // if an include file has been changed, all files will be re-compiled
        if(filepath.indexOf('.inc.') > -1)
            return true;

        // might not be the most efficient way to do this
        var srcDir = filepath.split('/');
        var filename = srcDir[srcDir.length - 1];
        delete srcDir[srcDir.length - 1];
        srcDir = srcDir.join('/');
        var destDir = srcDir.replace(/less/g, 'css');

        grunt.config('less.development.files', [{
            src: filename,
            dest: destDir,
            expand: true,
            cwd: srcDir,
            ext: '.css',
            extDot: 'last'
        }]);
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['less:development']);
};

答案 1 :(得分:0)

我不确定您对问题的当前标题的意思 Grunt只关注更改文件。你的意思是那是一个问题吗?这是watch任务的预期行为,它将监视为更改指定的文件并运行您指定的任务 - 在本例中为LESS编译。

我对您的文件进行了一些更改。其中一些是简化的,一些是改变的,保持脚本的灵活性和可扩展性。

首先通过运行:

安装underscore作为依赖项
npm install underscore --save-dev

然后对Gruntfile.js

进行以下更改
module.exports = function(grunt) {

    var _ = require('underscore');

    var files = {
        app : {
            '<%= path.styles.css %>/styles.css' : '<%= path.styles.less %>/*.less'
        },
        vendor : {
            '<%= path.styles.css %>/styles-vendor.css' : '<%= path.styles.vendor %>/*.less'
        },
        admin : {
            '<%= path.styles.css %>/styles-admin.css' : '<%= path.styles.admin %>/*.less'
        }
    }

    function all() {
        'use strict';
        var allfiles = {},
            i = {};

        for (i in files) {
            _.extend(allfiles, files[i]);
        }
        return allfiles;
    }

    grunt.initConfig({
        path : {
            media : 'media',
            styles : {
                css: 'media/css',
                less: 'media/less',
                admin: 'media/admin/less',
                vendor: '<%= path.styles.less %>/vendor'                
            }
        },
        less: {
            development: {
                options: {
                    compress: false,
                    yuicompress: true,
                    optimization: 2
                },
                files: (all())
            },
            production: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: (all())
            }
        },
        watch: {
            styles: {
                files: ['<%= path.media %>/**/*.less'],
                tasks: ['less:development'],
                options: {
                    nospawn: true
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-watch');

    // run several tasks as default (handy for complex projects)
    grunt.registerTask('dist', [ // run with 'grunt dist'
        'less:production'
    ]);
    grunt.registerTask('dev', [ // default, will run with 'grunt' only
        'less:development'
    ]);

    grunt.registerTask('default', 'dev');
};

如果您想要实际编译文件集单独files.appfiles.vendor&amp; files.admin),您可能需要拆分更多的任务,如下:

        less: {
            app: {
                options: {
                    compress: false,
                    yuicompress: true,
                    optimization: 2
                },
                files: files.app
            },
            vendor: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: files.vendor
            },
            admin: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: files.admin
            },
            development: {
                options: {
                    compress: false,
                    yuicompress: true,
                    optimization: 2
                },
                files: (all())
            },
            production: {
                options: {
                    compress: true,
                    yuicompress: true,
                    optimization: 2
                },
                files: (all())
            }
        },
        watch: {
            all: {
                files: ['<%= path.media %>/**/*.less'],
                tasks: ['less:development'],
                options: {
                    nospawn: true
                }
            },
            app : {
                files: ['<%= path.styles.less %>/*.less'],
                tasks: ['less:app'],
                options: {
                    nospawn: true
                }
            },
            vendor : {
                files: ['<%= path.styles.vendor %>/*.less'],
                tasks: ['less:vendor'],
                options: {
                    nospawn: true
                }
            },
            admin : {
                files: ['<%= path.styles.admin %>/*.less'],
                tasks: ['less:admin'],
                options: {
                    nospawn: true
                }
            }
        }

然后你可以运行其中任何一个:

grunt watch:app
grunt watch:vendor
grunt watch:admin

您可以随时选择直接运行任务:

grunt less:app
grunt less:vendor
grunt less:admin

希望这有帮助!请注意,我没有测试过这个。