在「grunt的初次使用」的基础上,这一篇继续对grunt进行探索研究。这一次不再使用php进行include静态文件,而是在html里面引入。然后主要将grunt用于两个大的方向,一个是用于开发期间,一个用于上线前期打包。使用到的插件可能有些更换。具体目录如下,src目录用于开发与维护,dist目录是打包后的项目,用于上线:
├─ dist/
├─ css/
├─ images/
├─ js/
└─ view/
└─ src/
├─ css/
├─ images/
├─ js/
├─ sass/
└─ view/
在开发期间,使用到的grunt插件如下,watch插件用了监听文件,一旦文件被修改,可以让它触发浏览器自动刷新:
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.12.0",
"grunt-contrib-sass": "^0.9.2",
"grunt-contrib-watch": "^0.6.1"
}
图片不需要压缩,css使用sass编译,js使用了requirejs,并使用jshint进行检错。其中sass编译好后会在同一目录下生成对应的css目录与文件。jshint的具体配置参考「例子」。
sass: {
dev: {
options: {
style: 'expanded'
},
files: [{
expand: true,
cwd: 'src/sass/',
src: ['**/*.scss'],
dest: 'src/css/',
ext: '.css'
}]
}
},
jshint: {
options: {
curly: true,
newcap: true,
eqeqeq: true
// ...
},
files: {
src: ['Gruntfile.js', 'src/**/*.js']
}
}
在开发结束后,接下来就是让项目上线了,于是就有了打包项目的过程。看过张云龙博客里讲的「大公司里怎样开发和部署前端代码?」,于是便有了非覆盖式发布和静态文件hash,用到了「grunt-filerev」和「grunt-usemin」这两个插件。网上有很多教程都是图片、css、js文件同一时间进行hash,但我觉得这样不妥,毕竟css(js)代码里引用到了图片,得先图片进行hash后替换了css(js)里引用的路径,然后再对css(js)进行hash才能保证哪些文件是修改过的。
打包分四个步骤。按顺序分别是图片的打包、css文件的打包、js文件的打包、html文件的打包。使用到的插件如下:
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-clean": "^0.7.0",
"grunt-contrib-copy": "^0.8.2",
"grunt-contrib-cssmin": "^0.14.0",
"grunt-contrib-htmlmin": "^0.6.0",
"grunt-contrib-imagemin": "^1.0.0",
"grunt-contrib-jshint": "^0.12.0",
"grunt-contrib-requirejs": "^0.4.4",
"grunt-contrib-sass": "^0.9.2",
"grunt-contrib-watch": "^0.6.1",
"grunt-css-sprite": "^0.2.2",
"grunt-filerev": "^2.3.1",
"grunt-include-replace": "^3.2.0",
"grunt-newer": "^1.1.1",
"grunt-replace": "^0.11.0",
"grunt-usemin": "^3.1.1",
"load-grunt-tasks": "^3.3.0",
"time-grunt": "^1.2.1"
}
首先得将dist目录给删除掉,因为是非覆盖式部署,所以删掉一些过期用不到的静态文件。第一个步骤是图片打包,将需要合并的图片合并了(并修改对应的css文件)放置于临时目录(tmp),不需要合并的图片则复制粘贴到临时目录(tmp)。然后对临时目录里的图片进行压缩,最后hash后放置于dist生产环境目录。
// 步骤一:对图片进行打包
grunt.registerTask('img', [
'clean:dist',
'sprite',
'copy:images',
'imagemin',
'filerev:img'
]);
第二个步骤是css文件的打包,先用sass将css压缩到临时目录(tmp)中,接着用usemin替换掉里面的已经hash的图片资源,最后将css文件进行hash后放置于dist生产环境目录。
// 步骤二:对css进行打包
grunt.registerTask('css', [
'sass:dist',
'usemin:css',
'filerev:css'
]);
第三个步骤是js文件的打包,用的是requirejs插件将js文件合并压缩到临时目录(tmp),然后替换掉文件里的图片资源路径,最后hash到生产环境目录(dist),并把不需要hash的第三方库复制到dist生产环境目录。
// 步骤三:对js进行打包
grunt.registerTask('js', [
'requirejs',
'usemin:js',
'filerev:js',
'copy:js'
]);
第四个步骤则是html文件的打包,先用grunt-replace把里面的php include替换成特定的模式放置于临时目录(tmp),然后再用grunt-include-replace把html依赖的html片段复制粘贴到一个html中,紧接着替换到html中的已hash的静态文件(包括css,js,image),最后将html压缩至dist目录下。
// 步骤四:对html进行打包
grunt.registerTask('html', [
'replace:before',
'includereplace',
'usemin:html',
'replace:after',
'htmlmin',
'clean:tmp'
]);
最后如果你想问我为什么上面的四个步骤不直接写成一个task呢,我也无能为力。我试过写成一个task,后果则是文件里的图片资源路径没能够替换成功,可能是在一个task内usemin插件无法执行多次,于是我就分类写成四个了。 最后总结一下,以上的方式的好处就在于开发时期不需要去合并压缩文件,方便调试。而生产环境则是尽可能去合并压缩,减少用户的请求时间。