前端使用 gulp 解決多專案快取問題

Gaara發表於2018-11-27

目前使用例子的專案初始目錄及檔案如下:

前端使用 gulp 解決多專案快取問題
因為本文所講的是多目錄多檔案加 hash ,所以特意挑了幾個簡單但是有代表性的專案。

我們從0開始配置:

1、環境配置

在專案根目錄啟動 Git Bash(或其他命令列工具)

  • 全域性安裝 node、npm (省略)

  • 初始化 npm

npm init -y  // -y 即預設同意所有基礎設定
複製程式碼

前端使用 gulp 解決多專案快取問題
此時本地會生成 package.json 配置檔案

前端使用 gulp 解決多專案快取問題

  • 本地安裝 gulp 及與該需求相關的幾個外掛
npm install --save-dev gulp // gulp
npm install --save-dev run-sequence // 設定外掛執行順序
npm install --save-dev gulp-rev // 新增 hash
npm install --save-dev gulp-clean // 清理檔案
npm install --save-dev gulp-minify-css // css 程式碼壓縮
npm install --save-dev gulp-uglify // js 程式碼壓縮
npm install --save-dev gulp-rev-collector //html 替換檔案版本

//也可以合併在一起安裝
npm install --save-dev gulp run-sequence gulp-rev gulp-clean gulp-minify-css gulp-uglify gulp-rev-collector
複製程式碼

安裝過程會有點慢,安裝完成後本地會生成 node_modules 資料夾,並且 package.json 檔案開啟后里面會有幾個外掛的基本資訊

前端使用 gulp 解決多專案快取問題

  • 根目錄下建立一個 js 檔案用來配置 gulp 資訊:gulpfile.js

完成以上配置後,此時我們的根目錄應該是如下樣子:

前端使用 gulp 解決多專案快取問題

2、配置 gulifile.js

直接貼程式碼,看效果

//引入gulp和gulp外掛
 var gulp = require('gulp'),
     runSequence = require('run-sequence'),
     rev = require('gulp-rev'),
     clean = require('gulp-clean'),
     minifycss=require('gulp-minify-css'),
     uglify=require('gulp-uglify'),
     revCollector = require('gulp-rev-collector');
 
 //定義css、js原始檔路徑
 var cssSrc = 'projectSrc/**/*.css',            //選擇目錄下所有css
       jsSrc = 'projectSrc/**/*.js',     //選擇目錄下所有css
       srcExclude = '!./node_modules/**/*',    //排除node_modules中的檔案
       htmFile = 'projectSrc/**/*.htm',
       htmlFile = 'projectSrc/**/*.html',
       jsonFile = 'projectSrc/**/*.json',
       pngFile = 'projectSrc/**/*.png',
       jpgFile = 'projectSrc/**/*.jpg',
       svgFile = 'projectSrc/**/*.svg',
       gifFile = 'projectSrc/**/*.gif',
       fontFile = 'projectSrc/**/*.ttf',
       jsCompressPath = 'projectOut/**/*.js',    //壓縮Publish中的js
       cssCompressPath = 'projectOut/**/*.css',    //壓縮Publish中的css
       replaceHtm = 'projectOut/**/*.htm'; //替換htm中引用css和js名
 
 
 //CSS生成檔案hash編碼並生成 rev-manifest.json檔名對照對映
 gulp.task('revCss', function(){
     // return gulp.src([cssSrc, srcExclude])
     return gulp.src(cssSrc)
         .pipe(rev())
         .pipe(gulp.dest('projectOut'))
         .pipe(rev.manifest())
         .pipe(gulp.dest('rev/css'));
 });
 
 //js生成檔案hash編碼並生成 rev-manifest.json檔名對照對映
 gulp.task('revJs', function(){
     // return gulp.src([jsSrc, srcExclude])
     return gulp.src(jsSrc)
         .pipe(rev())
         .pipe(gulp.dest('projectOut'))
         .pipe(rev.manifest())
         .pipe(gulp.dest('rev/js'));
 });
 
 
 //Html替換css、js檔案版本
 gulp.task('revHtml', function () {
     return gulp.src(['rev/**/*.json', replaceHtm])
         .pipe(revCollector())
         .pipe(gulp.dest('projectOut'));
 });


 //拷貝htm、html、json、圖片、字型
 gulp.task('copy', function(){
     return gulp.src([htmFile, htmlFile, jsonFile, pngFile, jpgFile, svgFile, gifFile, fontFile])
         .pipe(gulp.dest('projectOut'));
 });
 
 //壓縮JS
 gulp.task('jscompress', function(){
     return gulp.src(jsCompressPath)
         .pipe(uglify())
         .pipe(gulp.dest("projectOut"));
 });
 
 //壓縮CSS
 gulp.task('csscompress', function(){
     return gulp.src(cssCompressPath)
         .pipe(minifycss())
         .pipe(gulp.dest("projectOut"));
 });

 //開發構建
 gulp.task('dev', function (done) {
     condition = false;
     runSequence(
         ['clean'],
         ['revCss'],
         ['revJs'],
         ['copy'],
         ['revHtml'],
         ['jscompress'],
         ['csscompress'],
         done);
 });
 
 gulp.task('clean', function(){
     gulp.src('rev',{read:false}).pipe(clean());
     return gulp.src('projectOut',{read:false}).pipe(clean());
 });

gulp.task('default', ['dev']);
複製程式碼

我把輸出的檔案單獨放在一個資料夾下,這樣便於清理和保護原始碼。以後每次改動程式碼就在原資料夾裡面修改,修改完後構建一下就可以。

命令列跑一下 gulp 就OK了

gulp
複製程式碼

前端使用 gulp 解決多專案快取問題

我們來看一下成果:

前端使用 gulp 解決多專案快取問題

看,是不是加上 hash 了?很簡單是不是?不只檔案加上了,html 中的引用也加上了。

前端使用 gulp 解決多專案快取問題

等等

難道你以為這就完事了?這樣加 hash 是有 bug 的!這樣加相當於每次都給 js/css 重新命名了一次,容易出錯。

其實還有一種更好的方式,不過就需要修改 gulp 原始檔中的幾行程式碼了~~

老規矩,直接上程式碼

  • node_modules/gulp-rev/index.js
135行:manifest[originalFile] = revisionedFile;
改為:manifest[originalFile] = originalFile + '?v=' + file.revHash;
複製程式碼
  • node_modules/rev-path/index.js
9行:return modifyFilename(pth, (filename, ext) => `${filename}-${hash}${ext}`);
改為:return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);
複製程式碼
  • node_modules/gulp-rev-collector/index.js
40行:var cleanReplacement =  path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' );
改為:var cleanReplacement = path.basename(json[key]).split('?')[0];
複製程式碼

改完後執行下

前端使用 gulp 解決多專案快取問題

總結一下

前端使用 gulp 解決多專案快取問題 到此就告一段落了,在文章最後,總結一下使用過程中碰到的一些坑和使用的一些理解。

  • html/htm 中檔案的引用路徑要寫到外層 比如要在 login.html 中引用 login.js 檔案,路徑要寫 '../login/login.js' ,而不能直接寫成 'login.js'

  • runSequence 執行排序的時候,html替換css/js的外掛 要放到 hash外掛 和 copy外掛 後面,不然html中引用的檔案不會加hash

  • 註釋掉的 // return gulp.src([jsSrc, srcExclude]) 第二個引數 srcExclude = '!./node_modules/**/*' 是指排除 node_modules 下的檔案


最後提一個問題吧,乍聽起來覺得我說的沒什麼問題,當你想明白後你會覺得我問的很白痴

前端使用 gulp 解決多專案快取問題
問題:按最後的方法構建完成後,js/css 檔案本身怎麼不加 hash 了?


以上

相關文章