优化你的Grunt构建

jopen 8年前

 

在前端开发的今天,如果没用过Grunt或Gulp你还真就不好意思和人打招呼的(今天先说Grunt)。因为前端开发变得越来越复杂,前端工程化也越来越重要。当然,相信读者都能快速通过Grunt完成自己的前端工作流(workflow),下面是一个常见的Gruntfile.js, 它也的确能很好地工作。

module.exports=function(grunt){   grunt.initConfig({    pkg:grunt.file.readJSON('package.json'),    concat:{     dist:{      src:['src/js/jquery.js','src/js/index.js','src/js/main.js'],      dest:'dist/build.js',     }    },    imagemin:{     options:{      cache:false     },     dist:{      files:[{       expand:true,       cwd:'src/',       src:['**/*.{png,jpg,gif}'],       dest:'dist/'      }]     }    }   });   grunt.loadNpmTasks('grunt-contrib-concat');   grunt.loadNpmTasks('grunt-contrib-imagemin');   grunt.registerTask('default',['concat','imagemin']);  };

但随着你的项目迭代,你很可能会加入更多的构建task,然后你的Gruntfile.js很可能会变成几百行,甚至上千行的大文件,而且,通常在这个时候,你也很可能会遇到构建太慢的尴尬,简单的一次文件修改要花费数秒,甚至更长的时间才能完成构建。这种体验就好比在一个2G内存的电脑上,同时开着10多个Sublime在写代码一样,影响工作效率不说,更影响心情。本文将与大家一起探讨Grunt在以下两方面的优化:

1. 瘦身Gruntfile.js

2. 减少构建任务时间

Gruntfile.js瘦身

1. 使用load-grunt-tasks(https://www.npmjs.com/package/load-grunt-tasks)此grunt插件会根据package.json加载相应的Grunt任务,帮我们省去了手动加载的麻烦。

2. 使用load-grunt-config(https://www.npmjs.com/package/load-grunt-config),这时你的Gruntfile.js会变得非常简单:

module.exports=function(grunt){    varpath=require('path');    require('load-grunt-config')(grunt,{      // Grunt任务配置目录      configPath:path.join(process.cwd(),'grunt/config'),      // 加载Grunt任务并初始化      loadGruntTasks:{        pattern:['grunt-*'],        config:require('./package.json'),        scope:'devDependencies'      }    });  };

减少构建任务时间

因为grunt任务是单进程串行执行,加上每个任务都会有文件IO,所以任务执行效率并不高(我们现在有项目一次JS修改变动的Grunt 执行花费甚至达到了10秒的级别,当然前端代码文件多也是一个原因)。根据本人亲身体验,大于2S的构建时间,就能让你在开发中感觉到中断:文件修改保存后,马上去刷新浏览器,是看不到文件修改效果的。所以减少构建时间非常有必要。

1. 说到构建时间,首先就得知道我们每个构建任务花费的时间。这时有两个插件可以使用:time-grunt(https://www.npmjs.com /package/time-grunt)和grunt-timer(https://www.npmjs.com/package/grunt- timer)。time-grunt在构建完成后,会给出每个任务的耗时及占总耗时的百分比。但如果有watch任务存在,是看不到这个时间统计结果的,这时我们可以用grunt-timer;

2. 另一个不得不提到的插件是grunt-newer(https://www.npmjs.com/package/grunt-newer)。有了这个插件,我们就可以做到文件更改后,增量更新,而不是对所有的文件去执行任务task。此插件的使用也是非常简单,只需要在原来任务前加上newer:即可

watch:{    css:{      files:'src/sass/**/*.scss',      //tasks: ['compass:dev']    },    js:{      files:'src/js/**/*.js',      tasks:['newer:concat']    }  }

3. 使用grunt-concurrent(https://www.npmjs.com/package/grunt-concurrent)或 grunt-parallel(https://www.npmjs.com/package/grunt-parallel)并行运行你的构建任务

4. 使用jit-grunt(https://www.npmjs.com/package/jit-grunt)按需加载你的Grunt任务。当然我们用下面的代码,简单地实现此功能:

grunt.registerTask('dev',[],function(){    grunt.loadNpmTasks('grunt-contrib-clean');    grunt.loadNpmTasks('grunt-contrib-copy');    grunt.loadNpmTasks('grunt-express-concat');    grunt.loadNpmTasks('grunt-compass');    grunt.loadNpmTasks('grunt-contrib-watch');    grunt.loadNpmTasks('grunt-newer');    grunt.task.run(     'clean:dev',     'compass:dev',     'concat',     'watch'    );  });

5. 如何上面你都尝试了,构建时间还是让你无法接受,或许你应该试试Gulp(https://www.npmjs.com/package/gulp)