給資源文件添加指紋(Gulp版)


至於為什么要費盡心思地給文件添加指紋,請參看前端靜態資源緩存控制策略。這次要達到的小目標就是生成的資源文件能夠被客戶端緩存,而在文件內容變化后,能夠請求到最新的文件。

需要用到的 gulp 插件是 gulp-rev2 ,看清楚了,不是 gulp-rev + gulp-rev-collector 的蹩腳組合,而是 gulp-rev2

gulp-rev2 的設計思路:

  1. 根據文件的內容 file.contents 生成文件指紋(hash值);

  2. 根據前面生成的文件指紋集合成一張(源文件,構建文件)映射對照表(並保存在清單文件 rev-manifest.json 中);

  3. 根據前面生成的映射對照表級聯更新存在引用的父文件;

下面以一個具體的栗子為例進行實踐。

栗子的目錄結構是這樣的:

其中包含一個 css 樣式源文件 .demo/demo.css,內容如下

a { background: url(../images/road.jpg); }
div { background: url(../images/a+b.jpg); }

接下來使用 gulp 進行構建,新建兩個任務,一個構建 image,一個構建 css,

const gulp = require('gulp');
const rev2 = require('gulp-rev2');

gulp.task('build:image', ()=>{
    return gulp.src('./demo/**/*.{png,jpg,gif,ico}')
        .pipe(rev2())               // 生成文件指紋並修改文件名
        .pipe(gulp.dest('dist'))    // 輸出到 dist 目錄
        .pipe(rev2.manifest())      // 生成映射對照表 rev-manifest.js
        .pipe(gulp.dest('.'));      // 輸出到 gulpfile.js 同級目錄
});

gulp.task('build:css', ['build:image'], ()=>{
    return gulp.src('./demo/**/*.css')
        .pipe(rev2.update())        // 根據映射對照表更新存在引用的父文件
        .pipe(gulp.dest('dist'))
});

然后執行 gulp build:css,會發現根目錄下生成了 dist 目錄,並在里面存放了構建后的文件,

細心的同學可能已經發現在構建之后 ./demo/image/ 目錄下的圖片資源已經添加了文件指紋,

這時候打開生成的 ./dist/demo.css,內容如下

a { background: url(../images/road-f7ee61d96b.jpg); }
div { background: url(../images/a+b-d41d8cd98f.jpg); }

可以看到引用了圖片資源的 css 文件內容也得到了相應更新。只要圖片資源發生更新(文件指紋就會發生變化),引用者(css文件)也應該級聯更新。這兩個應該是始終同步的,否則就會出現驢唇不對馬嘴引用錯亂。

文件指紋總算加上了,但是這種修改文件名的方式並不總是所希望的。有時我們可能需要更簡單傳統的方式,也就是通過url參數(query string)的形式進行關聯。也就是我們期望的 css 可能是這樣的:

a { background: url(../images/road.jpg?_v_=f7ee61d96b); }
div { background: url(../images/a+b.jpg?_v_=d41d8cd98f); }

gulp-rev2 已經提供了這個選項,可以說是服務非常周到。只需要在原來的 gulp 代碼上簡單加一行配置項:

. . .
    .pipe(rev2({                // 生成文件指紋並修改文件名
        query: true,            // 以query string的方式進行指紋關聯
    }))
. . .

重新執行 gulp build:css,打開 ./dist/demo.css,會發現樣式表已經變成了我們預期的樣子:

a { background: url(../images/road.jpg?_v_=f7ee61d96b); }
div { background: url(../images/a+b.jpg?_v_=d41d8cd98f); }

你可以嘗試對單個圖片資源進行更新(比如 override 操作),gulp-rev2 只會更新發生變動的資源的指紋,這也是所期望的。

注意點

...
.pipe(rev2.manifest())      // 生成映射對照表 rev-manifest.js
.pipe(gulp.dest('.'));      // 輸出到 gulpfile.js 同級目錄

請確保 gulp-rev2 生成的清單文件 rev-manifest.js 輸出在 gulpfile.js 同級目錄下。這是因為 gulp-rev2 會在這個目錄進行讀取,否則將會導致錯誤。建議你在 .gitignore 文件中忽略掉該文件,因為它是構建生成的,沒有任何加入版本控制的需要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM