目前使用例子的專案初始目錄及檔案如下:
因為本文所講的是多目錄多檔案加 hash ,所以特意挑了幾個簡單但是有代表性的專案。我們從0開始配置:
1、環境配置
在專案根目錄啟動 Git Bash(或其他命令列工具)
-
全域性安裝 node、npm (省略)
-
初始化 npm
npm init -y // -y 即預設同意所有基礎設定
複製程式碼
此時本地會生成 package.json 配置檔案
- 本地安裝 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 檔案開啟后里面會有幾個外掛的基本資訊
- 根目錄下建立一個 js 檔案用來配置 gulp 資訊:gulpfile.js
完成以上配置後,此時我們的根目錄應該是如下樣子:
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
複製程式碼
我們來看一下成果:
看,是不是加上 hash 了?很簡單是不是?不只檔案加上了,html 中的引用也加上了。
等等
難道你以為這就完事了?這樣加 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 解決多專案快取問題 到此就告一段落了,在文章最後,總結一下使用過程中碰到的一些坑和使用的一些理解。
-
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 下的檔案
最後提一個問題吧,乍聽起來覺得我說的沒什麼問題,當你想明白後你會覺得我問的很白痴
問題:按最後的方法構建完成後,js/css 檔案本身怎麼不加 hash 了?以上