通过gulp自动构建项目前端静态资源的版本号,解决浏览器缓存导致更新不及时的问题。
问题描述
项目上线后,正常的改动升级不可避免,后端的改动还好说。服务发布完成就行了,但是前端页面因为有浏览器缓存导致js、css、图片等资源不会立即更新,这就导致项目升级后,客户端看到的可能还是旧的资源。需要手动清理浏览器缓存后再刷新才能更新到最新版本。 这就需要通过资源文件版本号来实现客户端同步的问题。
例如:
html页面中的js引用如下:
1
更改后的js引用如下:
1
这样如果浏览器发现src引用的有更改,则会重新从服务器端请求该文件,这样可以实现同步了。
如果只有一个html页面的话还好修改,但是一般现在的项目中html会有多个,js、css、图片也会有很多,所以手动管理就会变的很耗时间,这时候就需要一个自动化维护的手段来实现,现在nodejs很火,基于nodejs实现的gulp就是一个流式自动化构建工具。
原理
1、生成静态资源的文件hash码,保存到指定的文件。
2、如果文件发生变化,则文件的hash码也会跟着变化。
3、检查html文件中的js文件,如果文件的hash不变,则不替换,如果不同则替换。
实现方案
创建自动化构建的项目
1、新建项目名称buildpro
2、在buildpro文件夹下,创建node_modules文件及项目文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53D:\home\lehoon\develop\buildpro>npm instll module_name
npm WARN saveError ENOENT: no such file or directory, open 'D:\home\lehoon\develop\buildpro\package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open 'D:\home\lehoon\develop\buildpro\package.json'
npm WARN buildpro No description
npm WARN buildpro No repository field.
npm WARN buildpro No README data
npm WARN buildpro No license field.
+ module_name@1.0.0
added 43 packages in 5.119s
D:\home\lehoon\develop\buildpro>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install ` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (buildpro)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to D:\home\lehoon\develop\buildpro\package.json:
{
"name": "buildpro",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"module_name": "^1.0.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this ok? (yes) yes
安装gulp、配置gulp
1、安装gulp及插件
1
2
3
4npm install --save-dev gulp@3.9.1
npm install --save-dev gulp-rev@7.1.2
npm install --save-dev gulp-rev-collector@1.1.1
npm install --save-dev run-sequence@1.2.2
2、配置规则
修改node_modules\gulp_rev\index.js文件
1
2把 manifest[originalFile]= revisionedFile 修改成
manifest[originalFile]=originalFile+ '?v=' +file.revHash;
修改node_modules\gulp_rev_collector\index.js文件
1
2
3
4
5把if ( !_.isString(json[key]) ||path.basename(json[key]).replace(newRegExp( opts.revSuffix ),'' ) !== path.basename(key) ) {
修改成
if (!_.isString(json[key]) ||path.basename(json[key]).split('?')[0] !== path.basename(key)) {
通过修改regexp: newRegExp('([\/\\\\\'"])' +pattern, 'g'), 修改成 regexp: new RegExp( '([\/\\\\\'"])' + pattern + '(\\?v=\\w{10})?', 'g' ),
编写gulp任务文件
1、gulp默认找gulpfile.js执行,所以gulp的任务规则都放在项目根目录下的gulpfile.js中
2、gulp的规则文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44var gulp = require('gulp');
var runSequence = require('run-sequence');
var rev = require('gulp-rev');
var revCollector = require('gulp-rev-collector');
//要处理的项目工程目录
var programPath = 'D:/workspace/lshop';
var cssSrc=programPath + '/css/**/*.css';
var jsSrc=programPath + '/js/**/*.js';
//css文件生成hash编码,并保存到文件
gulp.task('revCss', function(){
console.log('=========' + cssSrc);
return gulp.src(cssSrc)
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('rev/css'));
});
//计算js文件的hash码并保存到文件
gulp.task('revJs', function(){
console.log('=========' + jsSrc);
return gulp.src(jsSrc)
.pipe(rev())
.pipe(rev.manifest())
.pipe(gulp.dest('rev/js'));
});
//替换html中的js版本号
gulp.task('revHtml', function(){
return gulp.src(['rev/**/*.json', programPath+'/*html'])
.pipe(revCollector())
.pipe(gulp.dest(programPath));
});
gulp.task('dev', function(done){
condition = false;
runSequence(['revCss'],['revJs'], ['revHtml'], done);
});
gulp.task('default', ['dev']);
3、然后切换到控制台下运行gulp命令即可。