Grunt watch&LESS – 如何让它更快? (只编译已更改的文件)

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

由于很长一段时间我抱怨说,当我改变任何LESS文件,所有得到重新编译。 我浪费时间,不能仅仅编译所需的东西。 但我希望它很聪明,所以如果有任何import它也会编译受影响的文件,而不仅仅是被修改的文件。

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

最后,我没有使用https://github.com/tschaub/grunt-newer,因为它不适合使用grunt-sync,但更重要的是,由于它不适合我的需求,因为它可以“对付LESSimport的东西,所以它不会编译相关的文件,但只有文件被更改,这不是“聪明”。

(可以对其进行定制以考虑这种东西,而且人们提供了一些要点,但没有任何官方的回购,所以很难find你需要的东西,但绝对值得一看。)


这是一个问题多次问,没有真正的或简单的答案。 看到:

你如何看多个文件,但只能在Grunt.js中运行更改后的文件的任务?

Grunt watch:只编译一个文件不是全部

Grunt只监视更改的文件

Grunt:观看多个文件,只编译更改

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

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

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

假设你有一个包含多个文件和目录(较less)的styles文件夹,那么我的解决scheme是定义一个白名单文件夹,我不会编译所有较less的文件,但只有那些已被更改。

Grunt-lessconfiguration: https : //gist.github.com/Vadorequest/bd46bb4d6c326e837710

Grunt-watchconfiguration: https : //gist.github.com/Vadorequest/b48bcfda2d0205ba3f95

文件夹架构: 文件夹架构

到目前为止,处理这个问题的“最简单”方法是重写grunt.watch事件,以检查更改后的文件是否会影响其他文件。 有几种方法取决于你自己的架构。 Mine很简单,因为影响所有其他文件的文件位于styles文件夹的根目录或子文件夹的内部。 所以我“只是”必须检查文件的filePath是否属于白名单。 如果是这样,那么我更新dynamicgruntconfiguration,更改属性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/在大约5秒钟之前对LESS文件进行简单的更改之后大约1秒钟更新浏览器,因为它必须编译所有的LESS文件并复制它们。 (我也进行了其他的性能改变,但它确实有助于实现这一目标!)

Interesting Posts