1. 程式人生 > >基於 gulp 的自動化構建之“靜態資源版本管理”--2017年12月"gulp-rev"版本8.1.0

基於 gulp 的自動化構建之“靜態資源版本管理”--2017年12月"gulp-rev"版本8.1.0


    我安裝完的版本號如下
    "gulp-rev": "^8.1.0",
    "gulp-rev-collector": "^1.2.3",

根據前人的經驗,和解決方法,發現12月的版本又有一些不同,為了讓大家更快的修改,釋出一下我的修改測試後的處理

以下為摘錄修改
在靜態資源版本管理方面,以前用過兩種方案(都是通過後端實現) : 第一種:獲取檔案最新修改時間。可以實現比較好的版本管理效果,但客戶端每一次訪問一個資原始檔,伺服器都會動態讀取一次該檔案的最新修改時間。對這種方案,頭腦有限,暫時無法評估其對效能和訪問速度的影響。但就版本管理效果來說,更傾向於這一種。 第二種:設定日期常量。版本管理效果非常差。 目前已實現的新方案如下:
在構建階段計算靜態資源的 hash 值,並將該值以引數的形式追加到de><link>de>、de><script>de>中的 URL。
大家需要知道的是,如果某個檔案發生了修改,我這裡會自動修改引用了該檔案的各個模組的view檔案。
此方案可實現真正的版本管理效果,並且可以確定對效能和訪問速度無影響。

1. 預設方案:

如果使用de >gulp-revde>+de >gulp-rev-collectorde>,預設效果如下:
"/css/style.css" => "/dist/css/style-1d87bebe.css" "/js/script1.js" => "/dist/script1-61e0be79.js" "cdn/image.gif" => "//cdn8.example.dot/img/image-35c3af8134.gif" 但是如果用上面方法,實現的是非覆蓋式更新:即每次修改檔案之後,生成帶新版本號的檔案,但是帶舊版本號的檔案不會被刪除,長此以往,最後你會發現資料夾裡累積了大量帶舊版本號的無用檔案。例如,style.css檔案經過三次更新之後,會累積一下三個檔案:

style-a3654c03aa.css
style-98c5f098bd.css
style-6e4cfcf9de.css

2. 改良方案:

期望效果:

href="dist/css/style.css" => href="dist/css/style.css?v=1d87bebe" src="dist/js/all.min.js" => src="dist/js/all.min.js?v=98c5f098bd" src="dist/img/image.gif" => src="dist/img/image.gif?v=35c3af8134"


原理:

(1)de >gulp-revde>根據檔案內容

計算生成一個hash 字串,如:de >98c5f098bdde>
(2)de >gulp-revde>生成一個對映表,列出對映關係

{ "all.min.js": "all.min.js?v=98c5f098bd" }

(3)de>gulp-rev-collectorde>根據該對映表 將de><link>de>、de><script>de>URL中的檔名de>all.min.jsde>替換為de>all.min.js?v=98c5f098bdde>

如何修改?

需要對de>gulp-revde>和de>gulp-rev-collectorde>進行修改。修改如下:

修改對映表中 屬性值的格式: 開啟de>node_modules\gulp-rev\index.jsde>


第134行 manifest[originalFile] = revisionedFile;

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

第164行 regexp: new RegExp( prefixDelim + pattern, 'g' ),

修改為:regexp: new RegExp( prefixDelim + pattern+'(\\?v=\\w{10})?', 'g' ),
修改生成檔案的檔名(原來是將 hash 值加入到檔名中,現要檔名保持不變):
開啟de >node_modules\rev-path\index.jsde>

第9行 return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`); 修改為: return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);

開啟de >node_modules\gulp-rev-collector\index.jsde>

第40行 var cleanReplacement = path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' ); 修改為: var cleanReplacement = path.basename(json[key]).split('?')[0];

避免引用 URL 中的版本號累積:de >
dist/js/all.min.js?v=6e4cfcf9dede>=>de >dist/js/all.min.js?v=54a62a8eb6?v=6e4cfcf9dede>
開啟de >node_modules\gulp-rev-collector\index.jsde>

第139行 regexp: new RegExp( dirRule.dirRX + pattern, 'g' ), 修改為: regexp: new RegExp( dirRule.dirRX + pattern+'(\\?v=\\w{10})?', 'g' ),


3. gulpfile.js 部分配置


var rev = require('gulp-rev'); var revCollector = require('gulp-rev-collector'); gulp.task('css-rev', function () { console.log('開始--計算 css 資源版本號,並生成對映表...'); return gulp.src(['./Data_Links/css/**/*.css']) .pipe(rev()) //.pipe(gulp.dest('./Data_Links/dist/css')) .pipe(rev.manifest({ path: 'rev-manifest-css.json' })) .pipe(gulp.dest('./Data_Links/rev')); }); gulp.task('css', ['css-rev'], function () { console.log('開始--修改 css 引用連結的資源版本號...'); return gulp.src(['./Data_Links/rev/rev-manifest-css.json', './src/tpls/**/*.html']) .pipe(revCollector()) .pipe(gulp.dest('./Data_Links/tpls')); }); gulp.task('js-rev',['css'],function () { console.log('開始--計算 js 資源版本號,並生成對映表...'); return gulp.src(['./Data_Links/js/**/*.js']) .pipe(rev()) // .pipe(gulp.dest('./Data_Links/dist/js')) .pipe(rev.manifest({ path: 'rev-manifest-js.json' })) .pipe(gulp.dest('./Data_Links/rev')); }); gulp.task('js', ['js-rev'], function () { console.log('開始--修改 js 引用連結的資源版本號...'); return gulp.src(['./Data_Links/rev/rev-manifest-js.json', './Data_Links/tpls/**/*.html']) .pipe(revCollector()) .pipe(gulp.dest('./Data_Links/tpls')); });


gulp.task在執行時,會先執行[]中的task任務,以上程式碼只要執行js這個任務,其他3個也會一起執行。
在這裡,我採用原始檔位置和生成後的位置不同的方式,css加版本號的時候引用的是原始檔位,js加版本號的時候引用的是css生成的檔案位,這個可以避免一個情況,js在生成的時候原始檔中css連結沒有版本號,而在生成的時候覆蓋css生成的版本號。也可以解決URL 中的版本號累積的問題?v=xxx?v=xxx

下面的二個被我註釋了,會備份css,js如果你需要可以開啟。
.pipe(gulp.dest('./Data_Links/dist/css')) 
.pipe(gulp.dest('./Data_Links/dist/js'))