简体   繁体   English

Grunt watch&LESS-如何使其更快? (仅编译已更改的文件)

[英]Grunt watch & LESS - How to make it faster? (only compiling the files that have been changed)

I have a basic application using LESS and grunt watch to compile changes on the fly. 我有一个使用LESS和grunt watch的基本应用程序来即时编译更改。

Since a very long time I was complaining about the fact that when I change any LESS file, all get re-compiled. 很长一段时间以来,我一直抱怨这样一个事实,当我更改任何LESS文件时,所有文件都会重新编译。 It was such a waste of my time not to be able to compile only what was needed. 无法仅编译所需的内容,这真是浪费我的时间。 But I wanted it smart, so if there were any import it would also compile the impacted files, not just the one that gets modified. 但是我希望它聪明,因此,如果有任何import它还可以编译受影响的文件,而不仅仅是被修改的文件。

Today I decided to fix this. 今天,我决定解决此问题。 It's not easy at all. 根本不容易。 Grunt watch don't take care of this, even using grunt-newer didn't work out, in both case it is required to write custom rules. Grunt手表不会照顾到这个问题,即使使用grunt-newer也不可行,在两种情况下都需要编写自定义规则。

Finally, I didn't use https://github.com/tschaub/grunt-newer because it doesn't play well with grunt-sync but more importantly, because it doesn't fit my needs with LESS, since it can't deal with the LESS import stuff and so it will not compile files related but only the files that have been changed, it's not "smart". 最后,我没有使用https://github.com/tschaub/grunt-newer,因为它在grunt-sync上不能很好地工作,但更重要的是,因为它不能满足我对LESS的需求,因为它可以不会处理LESS导入内容,因此它不会编译相关的文件,而只会编译已更改的文件,而不是“智能”的。

(It is possible to customize it to take into account that kind of stuff, and people provide some scripts on gist, but there isn't any official repo so it's kinda hard to find what you need, but definitely worth a look.) (可以对它进行定制,以考虑到这类内容,并且人们根据要旨提供了一些脚本,但是没有任何正式的仓库,因此很难找到您需要的东西,但是绝对值得一看。)


It's been a question asked multiple time with no real or easy answer to. 这是一个多次询问的问题,没有真正或简单的答案。 See: 看到:

How do you watch multiple files, but only run task on changed file, in Grunt.js? 如何在Grunt.js中观看多个文件,但仅在更改后的文件上运行任务?

Grunt watch: compile only one file not all Grunt watch:仅编译一个文件而不是全部

Grunt watch less on changed file only 咕unt声少观看更改的文件

Grunt: Watch multiple files, Compile only Changed Grunt:监视多个文件,仅编译已更改

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

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

My solution is a custom solution, specific to my app, but I hope it can be used for yours too! 我的解决方案是针对我的应用程序的自定义解决方案,但我希望它也可以用于您的应用程序! It's pretty simple. 很简单

Assuming you have a styles folder containing several files and directories (less), then my solution was to define a white list of folders for which I would not compile all less files, but only those that have been changed. 假设您有一个包含几个文件和目录(较少)的styles文件夹,那么我的解决方案是定义一个白名单文件夹,对于这些文件夹,我将不编译所有较少的文件,而仅编译已更改的文件。

Grunt-less config: https://gist.github.com/Vadorequest/bd46bb4d6c326e837710 无grunt的配置: https : //gist.github.com/Vadorequest/bd46bb4d6c326e837710

Grunt-watch config: https://gist.github.com/Vadorequest/b48bcfda2d0205ba3f95 咕-手表配置: https : //gist.github.com/Vadorequest/b48bcfda2d0205ba3f95

Folders architecture: 文件夹架构: 文件夹架构

The "easiest" way to deal with this so far is to override the grunt.watch event and so, to check whether or not the changed file may impact other files. 到目前为止,处理此问题的“最简单”方法是重写grunt.watch事件,然后检查更改后的文件是否可能影响其他文件。 There are several ways depending on your own architecture. 有几种方法取决于您自己的体系结构。 Mine is simple enough because files that impact all others are either at the root of the styles folder or inside sub folders. Mine很简单,因为影响其他所有文件的文件位于styles文件夹的根目录或子文件夹内部。 So I "just" had to check if the filePath of the file belongs to the white list or not. 因此,我“只是”不得不检查文件的filePath是否属于白名单。 If so, then I update the grunt config on the fly, changing the property src to match only the changed file name. 如果是这样,那么我将即时更新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;
        }
    } );

Basically, if I change a file named ayolan.less within the themes directory then here is what will be set in the memory when I'll update it. 基本上,如果我在themes目录中更改了一个名为ayolan.less的文件,则在更新文件时将在内存中进行设置。 (See https://gist.github.com/Vadorequest/b48bcfda2d0205ba3f95#file-watch-js-L80-L81 ) (参见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'
        }]
    }
}

This allows me now to use http://www.browsersync.io/ that will update the browser about 1 second after I make a simple change in a LESS file, that was about 5 seconds before, because it had to compile all LESS files and copy them. 这使我现在可以使用http://www.browsersync.io/ ,它将在我对LESS文件进行简单更改(大约5秒钟之前)后大约1秒钟更新浏览器,因为它必须编译所有LESS文件并复制它们。 (I made other performance changes as well, but it definitely helped to reach that goal!) (我也进行了其他性能更改,但这绝对有助于达到该目标!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM