gulp项目案例——js、css压缩并添加MD5戳
使用gulp要结合当前的项目架构做一定的处理,以实现自己想要的效果。
项目目录大概:
webapp
lib
lar-ui
page
folder1
index.css
index.html
index.js
folder2
index.css
index.html
index.js
gulpfile.js
先罗列一下使用到的插件:
1.gulp-load-plugins (自动加载package.json中的插件)
2.gulp-clean (清除)
3.gulp-clean-css (压缩css)
4.gulp-uglify (压缩js)
5.gulp-rev (生成MD5戳)
6.gulp-rev-collector (将html文件中的js、css替换成带有MD5戳的文件)
7.run-sequence (进行排序)
8.through2 (根据需求自定义插件)
上代码:
//加载gulp模块
var gulp = require('gulp');
//自动加载插件,能自动加载package.json里的插件,省去繁琐的定义
var plugins = require('gulp-load-plugins')();
//加载run-sequence模块,按照顺序执行
var runSequence = require('run-sequence');
//加载through2模块
var through2 = require('through2');
//定义路径对象,方便调取
var paths = {
webapp : './',
rev : './rev',
rev_js: './rev/js',
rev_css: './rev/css',
page: './page',
node_modules_js:'./node_modules_js/**/*.js',
node_modules_css:'./node_modules_css/**/*.css',
gulpfile_js:'./gulpfile.js',
src_js : './**/*.js',
src_css: './**/*.css',
src_html:'./page/**/*.html',
del_js: './**/*-*.js',
del_css:'./**/*-*.css',
rev_json:'./rev/**/*.json'
}
/**
* 自定义插件方法,修改rev.json文件内容
*/
function modify(modifier) {
return through2.obj(function(file,encoding, done) {
var content = modifier(String(file.contents));
file.contents = new Buffer(content);
this.push(file);
done();
});
}
/**
* 删除字段
* @param data json文件里的内容
* @returns {XML|string}
*/
function replaceSuffix(data) {
return data
.replace(/page\//gmi,"")
}
/**
* 删除字段,让路径统一
*/
gulp.task("replaceSuffix",function (cb) {
gulp.src([paths.rev_json])
//删除多余的字段,统一路径
.pipe(modify(replaceSuffix))
.pipe(gulp.dest(paths.rev))
.on('end', cb);
});
/**
* 删除掉上一次构建时创建的资源
*/
gulp.task('clean',function () {
return gulp.src([
paths.rev_json,
paths.del_js,
paths.del_css
]).pipe(plugins.clean());
});
/**
* 压缩js,生成时间戳
*/
gulp.task('uglifyJs',function(){
return gulp.src([paths.src_js,'!'+paths.node_modules_js,'!'+paths.gulpfile_js],{read:true})
//压缩js
.pipe(plugins.uglify())
//生成MD5
.pipe(plugins.rev())
//输出压缩生成时间戳后的js文件
.pipe(gulp.dest(paths.webapp))
//生成rev.json文件
.pipe(plugins.rev.manifest({merge:true}))
//输出json文件
.pipe(gulp.dest(paths.rev_js));
});
/**
* 压缩css,生成时间戳
*/
gulp.task('minifyCss',function(){
return gulp.src([paths.src_css,'!'+paths.node_modules_css],{read:true})
//压缩css
.pipe(plugins.cleanCss())
//生成MD5戳
.pipe(plugins.rev())
//输出压缩生成时间戳后的css文件
.pipe(gulp.dest(paths.webapp))
//生成rev.json文件
.pipe(plugins.rev.manifest({merge:true}))
//输出json文件
.pipe(gulp.dest(paths.rev_css));
});
/**
* 替换文件
*/
gulp.task('pagePath',function(){
return gulp.src([paths.rev_json,paths.src_html])
//将html文件中的js,css文件替换成压缩生成MD5戳的js、css文件
.pipe(plugins.revCollector())
//输出路径
.pipe(gulp.dest(paths.page));
});
/**
* 总入口
*/
gulp.task('default',function(){
runSequence(
'clean',
['uglifyJs','minifyCss'],
'replaceSuffix',
'pagePath'
);
});
这个项目中遇到的问题在于全局压缩后带有MD5戳的js,css路径都带有上一级(即html中引入的是index.css,带有时间戳的路径是page/index-sdkfjdie102.css),导致替换文件时出错,解决办法就是这段代码:
/**
* 自定义插件方法,修改rev.json文件内容
*/
function modify(modifier) {
return through2.obj(function(file,encoding, done) {
var content = modifier(String(file.contents));
file.contents = new Buffer(content);
this.push(file);
done();
});
}
这里用through2插件自定义另一个替换文件的插件,改变rev的json文件内容,使路径统一,最后使用run-sequence插件让期按指定的顺序执行。因为这个项目里html里的js,css文件都是同级目录应用,经过处理的json文件里会有同名不同戳的文件出现,导致后面的文件覆盖前面的文件
{
"index": "index-c144065c18",
"index": "index-a78095c25b"
}
如果项目中html中引入js、css方式是绝对路径,可以不作处理。如果跟我一样的话,解决方法看 gulp配合fs插件与path插件实现遍历目录得到子目录。