引言
眾所周知,在前端開發過程中,在文件版本更新之時,會面臨惱人的緩存問題(關于緩存相關問題說明可以參考這篇文章https://www.cnblogs.com/lyzg/p/5125934.html )。在更新版本時,最常見的解決由于緩存所引發的工程問題的方法不外乎兩種,一種是覆蓋式方法,一種是非覆蓋式方法。
所謂覆蓋式就是指更新js或者css文件時直接用待發布版本文件替換已發布版本文件,這種方法比較簡單,適用于在系統用戶量較少的情況下,而且在版本更新時還必須盡量在系統閑置期間進行操作。如每次更新css、js文件時不修改文件名,而是在html引用目錄中添加版本號,如......./js/index.js?v=12345678。
而非覆蓋式方法,是在版本更新時不直接用待發布版本替換已發布版本,而是每次都對待發布的文件修改文件名,并對html的引用目錄進行修改。這種方法稍微繁瑣,但是相對來講更加安全可靠。本文所介紹之方法即屬于這一種。
目的
本文目的是基于gulp自動化構建工具,實現一種非覆蓋式的js、css文件自動壓縮以及版本修改的方法。
構建前
原文件目錄結構:
原html文件
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<title>測試</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<article>
這里是測試.....
</article>
<script src="../js/jquery-1.12.3.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
構建后
構建生成目錄結構:
css版本更新中間文件
{
"index.css": "index_d41d8cd98f.min.css"
}
js版本更新中間文件
{
"index.js": "index_d41d8cd98f.min.js"
}
版本更新后html文件
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<title>測試</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="css/index_d41d8cd98f.min.css">
</head>
<body>
<article>
這里是測試.....
</article>
<script src="js/jquery-1.12.3.min.js"></script>
<script src="js/index_d41d8cd98f.min.js"></script>
</body>
</html>
實現過程
gulp是基于node.js,node.js以及gulp的安裝配置過程比較簡單,這里就不多說了。直接上gulp構建文件gulpfile.js如下:
/*
非覆蓋式自動化構建,靜態文件修改之后,修改其文件名,并更新html中對靜態文件的引用路徑
Created by fasily on 2017-03-13
*/
var gulp = require('gulp'),
rev = require('gulp-rev'),
revC = require('gulp-rev-collector'),
RevAll = require('gulp-rev-all'),
cssMin = require('gulp-csso'),
rename = require('gulp-rename'),
uglify = require('gulp-uglify'),
clearAll = require('del'),
runSequence = require('run-sequence');
// 開發js、css打版本入口
gulp.task('default', ['clearAll','dev']);
//開發構建
gulp.task('dev', function (done) {
runSequence(
['revCss'],
['revJs'],
['cssPathUpdate'],
['jsPathUpdate'],
['revHtml'],
done);
});
//定義css、js、html源文件路徑
var cssSrc = 'src/html/css/index.css',
jsSrc = 'src/html/js/index.js',
htmlSrc = 'src/html/test.html';
// css打版本
gulp.task('revCss', function() {
return gulp.src(cssSrc) //指定獲取到src下的所有css文件。
.pipe(cssMin()) //執行壓縮操作
.pipe(RevAll.revision({ hashLength: 10 }))
.pipe(rename({ //重命名
suffix: '.min'
}))
.pipe(gulp.dest('./dist/css'));//生成目標壓縮css文件
});
//生成css版本修改中間文件
gulp.task('cssPathUpdate', function() {
return gulp.src(cssSrc) //指定獲取到src下的所有css文件。
.pipe(cssMin()) //執行壓縮操作
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('./dist/css'));
});
// js打版本
gulp.task('revJs',function () {
return gulp.src(jsSrc) //指定獲取到src下的所有js文件。
.pipe(uglify()) //執行壓縮操作
.pipe(RevAll.revision({hashLength: 10 }))
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('./dist/js'));//生成目標壓縮js文件
});
//生成js版本修改中間文件
gulp.task('jsPathUpdate', function() {
return gulp.src(jsSrc) //指定獲取到src下的所有js文件。
.pipe(uglify()) //執行壓縮操作
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('./dist/js'));
});
//Html替換css、js引用文件版本
gulp.task('revHtml', function () {
return gulp.src(['dist/**/*.json', htmlSrc])
.pipe(revC())
.pipe(gulp.dest('dist'));
});
//清空dist文件夾
gulp.task('clearAll', function () {
clearAll('./dist/*');
});
另外需要修改gulp-rev-all目錄下revisioner.js文件第333行,修改為
filename = filename + '_' + file.revHash.substr(0, this.options.hashLength) + ext;
修改/rev-path/index.js第10行,修改為
return filename + '_' + hash + '.min' + ext;
修改gulp-rev-collector/index.js第11行,修改為
revSuffix: '_[0-9a-f]{8,10}-?.min'
總結
本文旨在通過介紹基于gulp的css、js文件壓縮以及版本修改來解決前端文件版本更新時所遇到的更新失效問題,由于時間關系,難免有不當或不細支出,望您提出寶貴意見和建議。
參考文章
https://www.zhihu.com/question/20790576
http://www.jb51.net/article/100652.htm