前端靜態資源版本更新與緩存之——經過gulp 在原html文件上自動化添加js、css版本號

原理

  1. 修改js和css文件javascript

  2. 經過對js,css文件內容進行hash運算,生成一個文件的惟一hash字符串(若是文件修改則hash號會發生變化)css

  3. 替換html中的js,css文件名,生成一個帶版本號的文件名html

方案

如今網上的方案都是生成一個新的dist目錄,裏面包含了要發佈的html,js,css等文件。可是在實際的公司的項目中,會有狀況不能生成新的HTML進行發佈,須要在原來的HTML文件上進行js ,css版本的替換. 這裏分享下我在實際項目中經過改動插件而後在原目錄結構下進行版本的控制方案。java

原html文件代碼node

<link rel="stylesheet" href="../css/default.css">
<script src="../js/app.js"></script>

預期效果:在原目錄結構下html文件代碼正則表達式

<link rel="stylesheet" href="../css/default.css?v=5a636d79c4">
<script src="../js/app.js?v=3a0d844594"></script>

1:安裝gulp和gulp插件
執行:npm

npm install --save-dev gulp
npm install --save-dev gulp-rev
npm install --save-dev gulp-rev-collector
npm install --save-dev run-sequence

2:編寫gulpfile.jsjson

//引入gulp和gulp插件
var gulp = require('gulp'),
    runSequence = require('run-sequence'),
    rev = require('gulp-rev'),
    revCollector = require('gulp-rev-collector');

//定義css、js源文件路徑
var cssSrc = 'css/*.css',
    jsSrc = 'js/*.js';


//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'));
});


//開發構建
gulp.task('dev', function (done) {
    condition = false;
    runSequence(
        ['revCss'],
        ['revJs'],
        ['revHtml'],
        done);
});


gulp.task('default', ['dev']);

執行gulp命令後的效果gulp

//rev目錄下生成了manifest.json對應文件
{
  "default.css": "default-803a7fe4ae.css"
}


<link rel="stylesheet" href="../css/default-803a7fe4ae.css">
<script src="../js/app-3a0d844594.js"></script>

很顯然這不是咱們須要的效果bash

3.更改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
31行if ( !_.isString(json[key]) || path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' ) !==  path.basename(key) ) {
更新爲: if ( !_.isString(json[key]) || path.basename(json[key]).split('?')[0] !== path.basename(key) ) {

再執行gulp命令,獲得的結果以下(效果正確):

<link rel="stylesheet" href="../css/default.css?v=803a7fe4ae">
<script src="../js/app.js?v=3a0d844594"></script>

可是假如咱們更改了css和js後,再執行gulp命令,獲得的結果會以下:

<link rel="stylesheet" href="../css/default.css?v=33379df310?v=803a7fe4ae">
<script src="../js/app.js?v=3a0d844594?v=3a0d844594"></script>

有沒有發現,會在版本號後面再添加一個版本號,由於gulp只替換了原來文件名,這樣又不符合預期效果了,因此咱們想到,還須要修改插件的替換正則表達式。

4.繼續更改gulp-rev-collector

打開node_modules\gulp-rev-collector\index.js
第107行 regexp: new RegExp( '([\/\\\\\'"])' + pattern, 'g' ),
更新爲: regexp: new RegExp( '([\/\\\\\'"])' + pattern+'(\\?v=\\w{10})?', 'g' ),

如今你無論執行多少遍gulp命令,獲得的html效果都是

<link rel="stylesheet" href="../css/default.css?v=5a636d79c4">
<script src="../js/app.js?v=3a0d844594"></script>

附上改事後的node_modules文件

相關文章
相關標籤/搜索