1. 程式人生 > >使用gulp自動化打包合並前端靜態資源(CSS、JS文件壓縮、添加版本號)

使用gulp自動化打包合並前端靜態資源(CSS、JS文件壓縮、添加版本號)

開發 替換 2.4 所有 vsu scom lena pfile sss

現在正在做的項目更新叠代比較頻繁,會經常對前端代碼打包部署,手動整合代碼文件很麻煩並且浪費時間,所以決定使用gulp來代替手工完成這項工作。

前端靜態資源在發版更新時會面臨客戶端瀏覽器緩存的問題(可參考這篇文章),解決這個問題可以采用兩類方法:覆蓋方法(引用資源時加版本號,不修改資源文件名)、非覆蓋方法(修改資源文件名),本篇文章主要采用的是第一種加版本號的方式,主要用gulp給靜態資源自動加版本號和壓縮CSS、JS。

原理:通過對JS,CSS文件內容進行Hash運算,生成一個文件的唯一Hash字符串,若對文件內容進行了修改則Hash號會發生變化。在HTML中引用文件時將版本號加在後面。

原始HTML:

1 <link href="css/global.css" rel="stylesheet" type="text/css" />
2 <script src="js/fun.js"></script>

使用後HTML:

1 <link href="css/global.css?v=b40a6f2a9f" rel="stylesheet" type="text/css" />
2 <script src="js/fun.js?v=3a08b5fa87"></script>

一、環境配置(安裝gulp)

首先安裝node、npm(此處省略)

安裝gulp以及用到的插件,並在項目目錄下創建文件gulpfile.js。

$ npm install --global gulp    --安裝全局gulp
$ npm install --save-dev gulp
$ npm install --save-dev gulp-rev
$ npm install --save-dev gulp-rev-collector
$ npm install --save-dev run-sequence
$ npm install --save-dev gulp-clean
$ npm install --save-dev gulp-minify-css
$ npm install 
--save-dev gulp-uglify

在項目目錄下創建文件gulpfile.js

項目目錄結構:

技術分享圖片

node_modules中是安裝的gulp和各種插件

二、編寫gulpfile.js

 1 //引入gulp和gulp插件
 2 var gulp = require(‘gulp‘),
 3     runSequence = require(‘run-sequence‘),
 4     rev = require(‘gulp-rev‘),
 5     clean = require(‘gulp-clean‘),
 6     minifycss=require(‘gulp-minify-css‘),
 7     uglify=require(‘gulp-uglify‘),
 8     revCollector = require(‘gulp-rev-collector‘);
 9 
10 //定義css、js源文件路徑
11 var cssSrc = ‘./**/*.css‘,            //選擇目錄下所有css
12       jsSrc = ‘./**/*.js‘,     //選擇目錄下所有css
13       srcExclude = ‘!./node_modules/**/*‘,    //排除node_modules中的文件
14       cssFile = ‘css/**/*‘,    //css文件夾
15       imageFile = ‘image/**/*‘,    //圖片文件夾
16       jsFile = ‘js/**/*‘,    //js文件夾
17       jsCompressPath = ‘Publish/js/*.js‘,    //壓縮Publish中的js
18       cssCompressPath = ‘Publish/css/*.css‘;    //壓縮Publish中的css
19 
20 
21 //CSS生成文件hash編碼並生成 rev-manifest.json文件名對照映射
22 gulp.task(‘revCss‘, function(){
23     return gulp.src([cssSrc, srcExclude])
24         .pipe(rev())
25         .pipe(rev.manifest())
26         .pipe(gulp.dest(‘rev/css‘));
27 });
28 
29 //js生成文件hash編碼並生成 rev-manifest.json文件名對照映射
30 gulp.task(‘revJs‘, function(){
31     return gulp.src([jsSrc, srcExclude])
32         .pipe(rev())
33         .pipe(rev.manifest())
34         .pipe(gulp.dest(‘rev/js‘));
35 });
36 
37 
38 //Html替換css、js文件版本
39 gulp.task(‘revHtml‘, function () {
40     return gulp.src([‘rev/**/*.json‘, ‘*.html‘])
41         .pipe(revCollector())
42         .pipe(gulp.dest(‘Publish‘));
43 });
44 
45 //拷貝除HTML外其他的文件
46 gulp.task(‘copy‘, function(){
47     return gulp.src([cssFile, jsFile, imageFile],{ base: ‘.‘})
48         .pipe(gulp.dest(‘Publish‘));
49 });
50 
51 //壓縮JS
52 gulp.task(‘jscompress‘, function(){
53     return gulp.src(jsCompressPath)
54         .pipe(uglify())
55         .pipe(gulp.dest("Publish/js"));
56 });
57 
58 //壓縮CSS
59 gulp.task(‘csscompress‘, function(){
60     return gulp.src(cssCompressPath)
61         .pipe(minifycss())
62         .pipe(gulp.dest("Publish/css"));
63 });
64 
65 //開發構建
66 gulp.task(‘dev‘, function (done) {
67     condition = false;
68     runSequence(
69         [‘clean‘],
70         [‘revCss‘],
71         [‘revJs‘],
72         [‘revHtml‘],
73         [‘copy‘],
74         [‘jscompress‘],
75         [‘csscompress‘],
76         done);
77 });
78 
79 gulp.task(‘clean‘, function(){
80     gulp.src(‘rev‘,{read:false}).pipe(clean());
81     return gulp.src(‘Publish‘,{read:false}).pipe(clean());
82 });
83 
84 
85 gulp.task(‘default‘, [‘dev‘]);

三、更改插件代碼

在項目目錄下直接執行gulp命令

$ gulp

會得到如下效果:

1 <link href="css/global-b40a6f2a9f.css" rel="stylesheet" type="text/css" />
2 <script src="js/fun-3a08b5fa87.js"></script>

需要更改gulp-rev、rev-path、gulpl-rev-collector插件的代碼:

1.node_modules/gulp-rev/index.js

第135行:manifest[originalFile] = revisionedFile;

更改為:manifest[originalFile] = originalFile + ‘?v=‘ + file.revHash;

2.node_modules/rev-path/index.js

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

更改為:return modifyFilename(pth, (filename, ext) => `${filename}${ext}`);

3.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@3.9.1
[email protected]
[email protected]
[email protected]
run-sequence@2.2.1
gulp-clean@0.4.0
gulp-minify-css@1.2.4
gulp-uglify@3.0.0

改完之後的效果

1 <link href="css/global.css?v=b40a6f2a9f" rel="stylesheet" type="text/css" />
2 <script src="js/fun.js?v=3a08b5fa87"></script>

四、小結

gulp的任務的執行是異步的,想要保證任務執行的順序,需要使用run-sequence插件

 1 gulp.task(‘dev‘, function (done) {
 2     condition = false;
 3     runSequence(
 4         [‘clean‘],
 5         [‘revCss‘],
 6         [‘revJs‘],
 7         [‘revHtml‘],
 8         [‘copy‘],
 9         [‘jscompress‘],
10         [‘csscompress‘],
11         done);
12 });

這裏順序執行任務:

先清除舊的rev和Pulish文件夾及其目錄下所有文件(clean),之後生成CSS文件名對照映射的JSON文件(revCSS),再之後生成JS文件名對照映射的JSON文件(revJS),之後替換掉HTML中的鏈接,加上版本號(revHTML),將除了HTML之外其他的靜態資源拷貝到Publish中(copy),然後壓縮Publish/js中的JS文件,並將壓縮後的文件替換掉原來的未壓縮文件(jscompress),最後壓縮Publish/css中的CSS文件,並替換掉未壓縮文件(csscompress)。

PS:

1.在寫路徑時,"!"是排除的標識,可以排除一些文件,如:

gulp.src([‘./**/*.css‘, ‘!./node_modules/**/*‘])

這裏選中的文件就是除了node_modules中的其他文件夾下的CSS文件

2.拷貝時若要保持路徑,需要加一個base選項,即:

gulp.src(‘Publish/css/*.css‘,{ base: ‘.‘})

之後也可以分別對測試環境和生產環境編寫任務,使用命令分開打包。

使用gulp自動化打包合並前端靜態資源(CSS、JS文件壓縮、添加版本號)