优化你的Grunt构建
在前端开发的今天,如果没用过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)