實現(xiàn)原理:
第一步:修改js和css文件序宦;
第二步:通過對js,css文件內(nèi)容進行hash運算睁壁,生成一個文件的唯一hash字符串(如果文件修改則hash號會發(fā)生變化);
第三步:替換html中的js,css文件名互捌,生成一個帶版本號的文件名;
最終效果
- 原h(huán)tml文件代碼
<link rel="stylesheet" href="../css/default.css">
<script src="../js/app.js"></script>
- 預(yù)期效果:在原目錄結(jié)構(gòu)下html文件代碼
<link rel="stylesheet" href="../css/default.css?v=5a636d79c4">
<script src="../js/app.js?v=3a0d844594"></script>
background:url("../images/none.png?v=8f204d4")
實現(xiàn)方法:
- 安裝gulp和gulp插件
npm install --save-dev gulp
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
- 編寫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',
jsSrc = 'js/*.js';
//為css中引入的圖片/字體等添加hash編碼
gulp.task('assetRev', function(){
return gulp.src(cssSrc) //該任務(wù)針對的文件
.pipe(assetRev()) //該任務(wù)調(diào)用的模塊
.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'])
.pipe(revCollector())
.pipe(gulp.dest('View'));
});
//開發(fā)構(gòu)建
gulp.task('default', function (done) {
condition = false;
runSequence( //需要說明的是秕噪,用gulp.run也可以實現(xiàn)以上所有任務(wù)的執(zhí)行钳降,只是gulp.run是最大限度的并行執(zhí)行這些任務(wù),而在添加版本號時需要串行執(zhí)行(順序執(zhí)行)這些任務(wù)腌巾,故使用了runSequence.
['assetRev'],
['revCss'],
['revJs'],
['revHtml'],
done);
});
執(zhí)行g(shù)ulp命令后的效果:
rev目錄下生成了manifest.json對應(yīng)文件
{
"default.css": "default-803a7fe4ae.css"
}
在html中如下:
<link rel="stylesheet" href="../css/default-803a7fe4ae.css">
<script src="../js/app-3a0d844594.js"></script>
顯然這不是我們需要的效果遂填。
- 修改gulp-rev和gulp-rev-collector
打開node_modules\gulp-rev\index.js
第144行 manifest[originalFile] = revisionedFile;
更新為: manifest[originalFile] = originalFile + '?v=' + file.revHash;
打開nodemodules\gulp-rev\nodemodules\rev-path\index.js
10行 return filename + '-' + hash + ext;
更新為: return filename + ext;
打開node_modules\gulp-rev-collector\index.js
40行的 let cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );
更新為: let cleanReplacement = path.basename(json[key]).split('?')[0];
打開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;
再執(zhí)行g(shù)ulp命令,得到的結(jié)果如下(效果正確):
<link rel="stylesheet" href="../css/default.css?v=803a7fe4ae">
<script src="../js/app.js?v=3a0d844594"></script>
background:url("../images/none.png?v=8f204d4")
但是假如我們更改了css和js后澈蝙,再執(zhí)行g(shù)ulp命令吓坚,得到的結(jié)果會如下:
<link rel="stylesheet" href="../css/default.css?v=33379df310?v=803a7fe4ae">
<script src="../js/app.js?v=3a0d844594?v=3a0d844594"></script>
有沒有發(fā)現(xiàn),會在版本號后面再添加一個版本號碉克,因為gulp只替換了原來文件名凌唬,這樣又不符合預(yù)期效果了,所以我們想到漏麦,還需要修改插件的替換正則表達式客税。
- 繼續(xù)更改gulp-rev-collector
打開node_modules\gulp-rev-collector\index.js
第107行 regexp: new RegExp( '([\/\\\\\'"])' + pattern, 'g' ),
更新為: regexp: new RegExp( '([\/\\\\\'"])' + pattern+'(\\?v=\\w{10})?', 'g' ),
現(xiàn)在你不管執(zhí)行多少遍gulp命令,得到的html效果都是
<link rel="stylesheet" href="../css/default.css?v=5a636d79c4">
<script src="../js/app.js?v=3a0d844594"></script>