【问题标题】:Grunt watch & LESS - How to make it faster? (only compiling the files that have been changed)Grunt watch & LESS - 如何让它更快? (仅编译已更改的文件)
【发布时间】:2016-01-07 19:34:35
【问题描述】:

我有一个基本应用程序,它使用 LESS 和 grunt watch 即时编译更改。

很长一段时间以来,我一直在抱怨这样一个事实,即当我更改任何 LESS 文件时,都会重新编译。不能只编译需要的东西真是浪费我的时间。但我希望它更聪明,所以如果有任何import,它也会编译受影响的文件,而不仅仅是那些被修改的文件。

今天我决定解决这个问题。这一点都不容易。 Grunt watch 不会处理这个问题,即使使用 grunt-newer 也没有用,在这两种情况下都需要编写自定义规则。

最后,我没有使用https://github.com/tschaub/grunt-newer,因为它不能很好地与 grunt-sync 配合使用,但更重要的是,因为它不符合我对 LESS 的需求,因为它无法处理 LESS 导入的东西因此它不会编译相关的文件,而只会编译已更改的文件,它不是“智能”的。

(可以自定义它以考虑到那种东西,人们在 gist 上提供了一些脚本,但没有任何官方 repo,所以很难找到你需要的东西,但绝对值得一看。)


这个问题被问了很多次,没有真正或简单的答案。见:

How do you watch multiple files, but only run task on changed file, in Grunt.js?

Grunt watch: compile only one file not all

Grunt watch less on changed file only

Grunt: Watch multiple files, Compile only Changed

https://github.com/tschaub/grunt-newer/issues/29

https://gist.github.com/cgmartin/10328349

【问题讨论】:

    标签: node.js gruntjs less grunt-contrib-less


    【解决方案1】:

    我的解决方案是一个自定义解决方案,特定于我的应用程序,但我希望它也可以用于您的应用程序!这很简单。

    假设您有一个包含多个文件和目录(更少)的 styles 文件夹,那么我的解决方案是定义一个文件夹的白名单,我不会为其编译所有更少的文件,而只那些已经改变的。

    Grunt-less 配置: https://gist.github.com/Vadorequest/bd46bb4d6c326e837710

    Grunt-watch 配置: https://gist.github.com/Vadorequest/b48bcfda2d0205ba3f95

    文件夹架构:

    到目前为止,“最简单”的处理方法是覆盖grunt.watch 事件等,以检查更改的文件是否会影响其他文件。有几种方法取决于您自己的架构。我的很简单,因为影响所有其他文件的文件要么位于 styles 文件夹的根目录中,要么位于子文件夹中。所以我“只是”必须检查文件的filePath 是否属于白名单。如果是这样,那么我会即时更新 grunt 配置,更改属性 src 以仅匹配更改的文件名。

    grunt.event.on('watch', function(action, filePath, watchedTargetName) {
            switch(watchedTargetName){
                /*
                Compile only what is needed.
                Based on a white list of sub folders within the "styles" directory.
                White listed folders will not require to compile all LESS file, but only the changed ones.
                Others will require to compile everything.
                 */
                case 'styles':
                    // Root path from where the files are located.
                    var rootPath = 'assets/linker/styles/';
                    // Path of the file
                    var filePathRelativeToRootPath = path.relative(rootPath, filePath);
                    // Grunt task name (see less.js)
                    var gruntTask = 'less';
                    // Sub task to use.
                    var subTaskName = 'dev';
                    // List of folders that don't need to recompile everything.
                    var whiteListFolders = [
                        'common',
                        'devices',
                        'layous',
                        'themes',
                        'views',
                    ];
    
                    if(action === 'changed'){
                        var isDir = path.dirname(filePath) !== '';
                        var dirName = filePathRelativeToRootPath.split(path.sep)[0];
    
                        // If the file is a directory and is belongs to the white list then we will override the grunt config on the fly to compile only that file.
                        if(isDir && _.contains(whiteListFolders, dirName)){
                            // We load the less config located at tasks/config/less.js
                            var config = grunt.config(gruntTask);
    
                            // Checks for any misconfiguration.
                            if(!config){
                                log.error('There is no config for the grunt task named ' + gruntTask);
                            }
    
                            if(!config[subTaskName]){
                                log.error('There is no sub task named ' + subTaskName + " for the the grunt task named " + gruntTask);
                            }
    
                            // Update the files.src to be the path to the modified file (relative to srcDir).
                            // Instead of updating all files, it will only update the one that has been changed.
                            config[subTaskName].files[0].src = filePathRelativeToRootPath;
                            grunt.config("less", config);
                            console.info('watcher LESS - The file ' + filePath + ' is in the white list and will be updated alone.');
                        }else{
                            console.info('watcher LESS - The file ' + filePath + ' is not is the white list, all LESS files will be updated.');
                        }
                    }
                    break;
            }
        } );
    

    基本上,如果我在themes 目录中更改了一个名为ayolan.less 的文件,那么当我更新它时,这就是将在内存中设置的内容。 (见https://gist.github.com/Vadorequest/b48bcfda2d0205ba3f95#file-watch-js-L80-L81

    {
        dev: {
            files: [{
                expand: true,
                cwd: 'assets/linker/styles/',
                src: 'themes/ayolan.less',// This has been changed in memory, for this specific watch event.
                dest: '.tmp/public/linker/styles/',
                ext: '.css'
            }]
        }
    }
    

    这使我现在可以使用http://www.browsersync.io/,它会在我对 LESS 文件进行简单更改后大约 1 秒更新浏览器,大约是 5 秒之前,因为它必须编译所有 LESS 文件并复制它们。 (我还进行了其他性能更改,但这绝对有助于实现该目标!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-23
      • 2018-08-22
      • 1970-01-01
      • 1970-01-01
      • 2013-02-11
      • 2011-12-10
      • 1970-01-01
      • 2014-12-29
      相关资源
      最近更新 更多