利用gulp進行靜態資源版本控制(url?v=md5)

遇到的問題

服務器端靜態資源更新,客戶端有緩存,未能獲取到最新的靜態資源,導致前端效果未達到預期。

期望

服務器端靜態資源更新后,客戶端訪問時能夠獲取到最新的靜態資源。客戶端盡量發送少的請求,服務器端未發生變化時,客戶端依然讀取本地緩存。盡量少的人工操作。

解決方案

借助基于nodejs的工具gulp,計算靜態資源的MD5值做為版本號追加在靜態資源的鏈接后,當靜態資源發生變更時,MD5亦會發生變化,客戶端會發起新的鏈接從而拉取到最新的靜態資源。

弊端:加載靜態資源的頁面必須不能緩存,否則無法加載到最新的靜態資源鏈接。頻繁更新靜態資源導致客戶端的緩存過大,不過對于現在PC或者手機來說,空間是足夠的。

實施步驟

以linux操作系統為例,注意各種版本號,目錄僅為示例,按實際需求位置安裝,注意操作用戶的權限。

為.html文件中引用的靜態添加版本號。

1.安裝nodejs

訪問NodeJS的官方網站,根據自己的操作系統下載對應的安裝包

http://nodejs.cn/download/

linux系統下載后解壓即可。

wget https://npm.taobao.org/mirrors/node/v8.4.0/node-v8.4.0-linux-x64.tar.gz

tar xf node-v8.4.0-linux-x64.tar.gz -C /opt/taobao/install/

配置全局命令

ln -s /opt/taobao/install/node-v8.4.0-linux-x64/bin/node /usr/local/bin

ln -s /opt/taobao/install/node-v8.4.0-linux-x64/bin/npm /usr/local/bin

2.可選步驟,npm為nodejs插件管理,因為是國外的下載源,可能網絡不穩定。淘寶建立了一個完整npmjs.org鏡像,可以用此代替官方版本(只讀),同步頻率目前為10分鐘一次以保證盡量與官方服務同步。

npm install cnpm -g --registry=https://registry.npm.taobao.org

配置全局命令

ln -s /opt/taobao/install/node-v8.4.0-linux-x64/bin/cnpm /usr/local/bin

cnpm和npm的功能一致,只是下載源不同。以下出現的npm和cnpm可以互換。

3.安裝全局的gulp

cnpm install gulp -g

配置全局命令

ln -s /opt/taobao/install/node-v8.4.0-linux-x64/bin/gulp /usr/local/bin

4.選擇一個目錄開始編寫腳本。此目錄為模塊位置,后續需要更改此位置下插件的源碼。

按默認配置創建模塊

cnpm init -y

會自動生成一個模塊描述文件package.json

5.安裝需要的插件

采用局部安裝,僅此模塊依賴

cnpm install --save-dev gulp

cnpm install --save-dev gulp-rev

cnpm install --save-dev gulp-rev-collector

cnpm install --save-dev gulp-asset-rev

cnpm install --save-dev run-sequence

安裝完成后package.json的文件內容如下(注意各插件版本號):


{

"name": "res_ver",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"keywords": [],

"author": "",

"license": "ISC",

"devDependencies": {

"gulp": "^3.9.1",

"gulp-asset-rev": "^0.0.15",

"gulp-rev": "^8.1.0",

"gulp-rev-collector": "^1.2.2",

"run-sequence": "^2.2.0"

}

}



6.編寫腳本

目錄未變更,創建一個文件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 opt = new Object();

//靜態資源的源目錄

opt.staticSrcFolder =?'/WEB-INF/classes/static';

//html文件的源目標

opt.htmlSrcFolder = '/WEB-INF/classes/templates';

//生成靜態資源的目錄。可與源目錄相同,會覆蓋。

opt.staticDestFolder = '/WEB-INF/classes/static';

//生成html文件的目錄。可與源目錄相同,會覆蓋。

opt.htmlDestFolder = '/WEB-INF/classes/templates';

// 為css中引入的圖片/字體等添加hash編碼

gulp.task('assetRev', function() {

return gulp.src(opt.staticSrcFolder + "/**/*.css") // 該任務針對的文件

.pipe(assetRev()) // 該任務調用的模塊

.pipe(gulp.dest(opt.staticDestFolder)); // 編譯后的路徑

});

// CSS、js生成文件hash編碼并生成 rev-manifest.json文件名對照映射。可加入.jpg、.png、.svg等

gulp.task('revStatic', function() {

return gulp.src([ opt.staticSrcFolder + "/**/*.css",opt.staticSrcFolder + "/**/*.js" ])

.pipe(rev())

.pipe(rev.manifest())

.pipe(gulp.dest(opt.staticDestFolder));

});

// Html替換css、js文件版本

gulp.task('revHtml', function() {

return gulp.src([ opt.staticDestFolder + '/**/rev-manifest.json', opt.htmlSrcFolder + '/**/*.html' ])

.pipe(revCollector())

.pipe(gulp.dest(opt.htmlDestFolder));

});

// 開發構建

//gulp.run是最大限度的并行執行這些任務,而在添加版本號時需要順序執行這些任務,故使用了runSequence.也有不使用runSequence的寫法,閱讀起來比較費勁。

gulp.task('default', function(done) {

condition = false;

runSequence(

[ 'assetRev' ],

[ 'revStatic' ],

[ 'revHtml' ],

done);

});


7.修改部分插件源碼

1.打開 模塊位置/node_modules/gulp-rev/index.js

修改134行 manifest[originalFile] = revisionedFile;

改為 manifest[originalFile] = originalFile + '?v=' + file.revHash;


2.打開 模塊位置/node_modules/rev-path/index.js

修改10行 return filename + '-' + hash + ext;

更新為: return filename + ext;


3.打開 模塊位置/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]).replace(new RegExp( opts.revSuffix ), '' ).split('?')[0];

修改163行 regexp: new RegExp( prefixDelim + pattern, 'g' ),

修改為: regexp: new RegExp( prefixDelim + pattern + '(\\?v=\\w{10})?', 'g' ),


4.打開 模塊位置/node_modules/gulp-asset-rev/index.js

修改78~80行:var verStr = (options.verConnecter || "-") + md5;

src = src.replace(verStr, '').replace(/(\.[^\.]+)$/, verStr + "$1");

改為:var verStr = (options.verConnecter || "") + md5;

src = src + "?v=" + verStr;

8.運行腳本觀察結果

可以在模塊目錄下直接運行命令gulp

或者在任意位置使用gulp?--gulpfile <gulpfile path>指定一個腳本執行。




待續

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容