1. 程式人生 > >gulp管理靜態資源緩存

gulp管理靜態資源緩存

class () 部署 ports hash .json ati name 靜態資源

前端項目在版本叠代的時候,難免會遇到靜態緩存的問題,明明開發的是ok的,但是一部署到服務器上,發現頁面變得亂七八糟,這是由於靜態緩存引起的。

技術分享圖片

從上面這張圖片可以看出,瀏覽器加載css,js等資源時,size一欄是from cache,也就是直接使用了本地的資源,而沒有向服務器請求。這樣做的好處是提升頁面渲染速度,壞處是當服務器的對應的文件發生變化時,瀏覽器卻還是使用緩存,造成布局混亂的問題。

解決辦法

一個比較原始的辦法是在修改了文件之後,手動改變文件名稱,然後再在html手動更新資源的path名稱。打個比方,你有一天更新了a.css的樣式,然後加個日期後綴,把它重命名為a-1221.css

,同時在應用這個css的html中改成:

<link href="./css/a-1221.css" rel="stylesheet"/>

這時,但瀏覽器發現需要加載這個樣式時,發現自己只有a.css,沒有a-1221.css,就會向服務器發起請求了。不過,很明顯,這種活大家是都不願意幹的,尤其是css文件一多的時候,絕對懵逼,所幸我們可以讓gulp來幫我們完成這些乏味的工作。

gulp-rev 和 gulp-rev-collector

這是兩個gulp的插件,gulp-rev可以根據靜態資源的得出文件的hash值,當文件內容發生改變時,這個hash值也會發生變化。並生成一個json文件,大概長這個樣子:

{
    "base/index.css": "base/index-c52f09f203.css"
}

文件的後綴變成了這個文件的hash值。gulpfile.js中的代碼如下:

var rev = require(‘gulp-rev‘);
var gulp = require(‘gulp‘);
gulp.task(‘revCss‘, function(){
  return gulp.src(cssUrl)//你存放css的目錄 
 .pipe(rev())        
 .pipe(rev.manifest())
 .pipe(gulp.dest(‘rev/css‘));//在rev/css目錄下生成json文件
});

這個插件只解決了問題的一部分,也就是,把文件變動和hash值關聯了起來,另一部分改變html的請求路徑還要靠第二個插件gulp-rev-collector來完成。這個插件完成的事情也很簡單,就是把html中的資源路徑,通過正則匹配,替換成更新後的路徑。代碼如下:

var gulp = require(‘gulp‘);
var revCollector = require(‘gulp-rev-collector‘);
 gulp.task(‘revHtml‘, function () {
  return gulp.src([‘rev/**/*.json‘, ‘views/*.html‘])
 .pipe(revCollector())
 .pipe(gulp.dest(‘views/inc/‘));
});

所以這兩個插件就解決問題了嗎?可惜並不是這樣。因為你的css文件名並沒有更改,還是原來的a.css,所以還需要一個插件幫我們解決重命名的問題。比如用來重命名文件的gulp-rename。

var rename = require("gulp-rename");
var json = require(‘./rev-manifest.json‘);//rev生成的文件

gulp.task(‘rename‘,function(){
  var json = require(‘./rev/css/rev-manifest.json‘);
  var Path = require(‘path‘);
  gulp.src("static/css/*.css")
  .pipe(rename(function (path) {
    path.basename  = json[path.basename + ‘.css‘].replace(‘.css‘, ‘‘);//改掉css文件名為含有hash值的文件名
  }))
  .pipe(gulp.dest("./dist"));
})

查詢參數管理緩存

查詢參數這種方法適用於前後端不分離的項目,因為這時再去重命名靜態文件就會顯得很麻煩。所以出現了這種做法,就是在靜態資源發生變化時,文件名不改變,但是html中請求路徑的查詢參數會發生變化,像下面這樣:

<link rel="stylesheet" href="/css/style.css?v=2h3h2ar">

這個查詢參數v對於後臺來說,沒有什麽意義,你完全可以改成a,b,c。但是當查詢參數的hash值發生變化時,卻會讓瀏覽器去向服務器發起請求,從而更新緩存。如果你想用這種方式,可以使用gulp-rev-query(github)插件和gulp-rev-collector-query,將文件名轉換成查詢字符串。(插件的一個bug是對於.min.css會解析錯誤)

{
  "base/index.css": "base/index.css?v=1ead88a42c"
}

下面是我參考作者的寫的一個,解決了min.js的問題,其實就是改了正則:


var through = require(‘through2‘);

module.exports = function(ver) {
    var ver = ver || ‘v‘
    // convert a-xxxxxxxx.css to a.css?ver=xxxxxxxx
    function hashToQuery(file) {
        var content = new String(file._contents);
        content = content.replace(/(.+)\-(.{7,10})(\..+)"/g, function(match, p1,p2,p3,offset,string){
            return  `${p1}${p3}?${ver}=${p2}"`
          });
        file._contents = new Buffer(content);
        file.ver = ver;
        return file;
    }
    return through.obj(function(file, encoding, callback) {
        callback(null, hashToQuery(file));
    });
};

最後,祝大家聖誕快樂!

gulp管理靜態資源緩存