1,说明:使用gulp为js和css静态文件添加版本号,升级服务器代码后,可以不用强制更新浏览器或清空缓存,优化用户体验。
本文主要参考http://www.jb51.net/article/100652.htm, 但是遇到一些小坑,特此记录
2,预期效果:在原目录结构下html文件代码
<link href ="../css/index.css?v=8f204d4">
3,实现方法:
前提:需要安装node.js 建议版本不要超过v12;本篇node版本为v11.5.0
1、安装gulp和gulp插件
打开node命令行,cd 进入到项目根文件夹(若安装失败,推荐国内的淘宝npm镜像,教程:https://blog.csdn.net/quuqu/article/details/64121812,使用方法将npm改为cnpm)
gulp版本3.9.1
npm install --save-dev gulp@3.9.1
npm install --save-dev gulp-rev
npm install --save-dev gulp-rev-collector
npm install --save-dev gulp-asset-rev
npm install --save-dev run-sequence
2、编写gulpfile.js
笔者是在templates文件夹( 存放html代码 )同级文件夹内创建的gulpfile.js
//引入gulp和gulp插件,
var gulp = require('gulp'),
assetRev = require('gulp-asset-rev'),
runSequence = require('run-sequence'),
rev = require('gulp-rev'),
revCollector = require('gulp-rev-collector');
//定义css、js源文件路径
var cssSrc = 'css/*.css', // 注意这里修改为你的源文件路径,例如笔者的项目css文件,设置为 static/css/main/*.css ,js同理。
jsSrc = 'js/*.js';
//为css中引入的图片/字体等添加hash编码
gulp.task('assetRev', function(){
return gulp.src(cssSrc) //该任务针对的文件
.pipe(assetRev()) //该任务调用的模块
.pipe(gulp.dest('src/css')); //编译后的路径
});
//CSS生成文件hash编码并生成 rev-manifest.json文件名对照映射
gulp.task('revCss', function(){
return gulp.src(cssSrc)
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('rev/css'));
});
//js生成文件hash编码并生成 rev-manifest.json文件名对照映射
gulp.task('revJs', function(){
return gulp.src(jsSrc)
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('rev/js'));
});
//Html替换css、js文件版本
gulp.task('revHtml', function() {
return gulp.src(['rev/**/*.json', 'View/*.html']) // 这里的View/*.html是项目html文件路径,如果gulpfile.js和html文件同在一级目录下,修改为return gulp.src(['rev/**/*.json', '*.html']);
.pipe(revCollector())
.pipe(gulp.dest('View'));// 注意这里是生成的新的html文件,如果设置为你的项目html文件所在文件夹,会覆盖旧的html文件,若上面的View/*.html修改了,这里也要相应修改,如果gulpfile.js和html文件同在一级目录下,修改为 .pipe(gulp.dest(''));
});
//开发构建
gulp.task('default', function(done) {
condition = false;
runSequence( //需要说明的是,用gulp.run也可以实现以上所有任务的执行,只是gulp.run是最大限度的并行执行这些任务,而在添加版本号时需要串行执行(顺序执行)这些任务,故使用了runSequence.
['assetRev'],
['revCss'],
['revJs'],
['revHtml'],
done);
});
3,修改插件
原文到了这里执行gulp查看更新效果,建议先不要执行。修改完成后再执行。
-- 1
打开node_modules\gulp-rev\index.js
134行:
manifest[originalFile] = revisionedFile;
更新为:
manifest[originalFile] = originalFile + '?v=' + file.revHash;
-- 2
打开 node_modules\rev-path\index.js
注意:原文这里的路径是打开nodemodules\gulp-rev\nodemodules\rev-path\index.js,根据你的具体情况进行修改。
9行 return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`);
更新为:return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);
17行 return modifyFilename(pth, (filename, ext) => filename.replace(new RegExp(`-${hash}$`), '') + ext);
更新为: return modifyFilename(pth, (filename, ext) => filename + ext);
-- 3
打开node_modules\gulp-rev-collector\index.js
40行:var cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );
更新为:var cleanReplacement = path.basename(json[key]).split('?')[0];
-- 4
打开node_modules\gulp-assets-rev\index.js
78行 var verStr = (options.verConnecter || "-") + md5;
更新为:var verStr = (options.verConnecter || "") + md5;
80行 src = src.replace(verStr, '').replace(/(\.[^\.]+)$/, verStr + "$1");
更新为:src=src+"?v="+verStr;
-- 5、更改gulp-rev-collector
打开node_modules\gulp-rev-collector\index.js
第173行
regexp: new RegExp( prefixDelim + pattern, 'g' ),
更新为 regexp: new RegExp( prefixDelim + pattern + '(\\?v=\\w{10})?', 'g' ),
4,执行gulp
1 执行gulp,查看html文件是否正确添加版本号
需要注意的是,运行gulp,通过快照如果文件没有修改过, 版本随机数并不会改变;只更改有变更的文件
模板:
var gulp = require('gulp'),
assetRev = require('gulp-asset-rev'),
runSequence = require('run-sequence'),
rev = require('gulp-rev'),
revCollector = require('gulp-rev-collector');
// var rev = require('gulp-rev-append');
var cssSrc = '*.css',
jsSrc='*.js';
// gulp.task('default',function(done){
// console.log('hello world');
// done();
// });
gulp.task('revCss', function(){
gulp.src(cssSrc)
.pipe(rev())
.pipe(gulp.dest('dist/'))
.pipe(rev.manifest({meger: true}))
.pipe(gulp.dest('dist/revCss'))
});
gulp.task('revJs', function(){
gulp.src(jsSrc)
.pipe(rev())
.pipe(gulp.dest("dist/"))
.pipe(rev.manifest({meger: true}))
.pipe(gulp.dest('dist/revJs'))
});
gulp.task('revHtml', function() {
// 这里的View/*.html是项目html文件路径,如果gulpfile.js和html文件同在一级目录下,修改为return gulp.src(['rev/**/*.json', '*.html']);
gulp.src(['dist/**/*.json', '*.html'])//replaceReved 是否可以重复替换 后缀Hash 默认是flase;
.pipe( revCollector({
replaceReved: true
}))
.pipe( gulp.dest('dist') );
// 注意这里是生成的新的html文件,如果设置为你的项目html文件所在文件夹,会覆盖旧的html文件,若上面的View/*.html修改了,这里也要相应修改,如果gulpfile.js和html文件同在一级目录下,修改为 .pipe(gulp.dest(''));
});
gulp.task('default', function(done) {
condition = false;
runSequence( //需要说明的是,用gulp.run也可以实现以上所有任务的执行,只是gulp.run是最大限度的并行执行这些任务,而在添加版本号时需要串行执行(顺序执行)这些任务,故使用了runSequence.
['revCss'],
['revJs'],
['revHtml'],
done);
});
// gulp.task('default',['dev']);
gulp.task('revHtml', function() {
gulp.src(['dist/**/*.json', '*.html'])
.pipe( revCollector({
replaceReved: true
}))
.pipe( gulp.dest('dist') );
});
如果在dist中,生成了多个内容相同的json文件,只是后面的版本号不同, 那么 gulp.src(['dist/**/*.json', '*.html']) 这里最好指定一下,
gulp.src(['dist/revJS/*.json','dist/revCss/*.json', '*.html']);