系统发版后客户端缓存更新方案
一。解决思路:
1. 利用gulp根据静态文件(JS,CSS,图片)内容生成对应的HASH值作为它的版本号,文件内容变化则版本号跟着变(需处理生成版本号的位置,不同路径下同名文件HASH值覆盖问题,JSP文件编码问题等,已在下面给出的gulpfile.js和环境配置中给出处理方案)。
- minify类型的引用需做特殊处理,jsp中做过minfy优化后,为它加版本号必须加到最后一个引用文件上,否则会出错,由于不同的jsp文件中每个minify引用的最后一个静态文件不同,所以需要新增一个公共minify_version.js 添加到需要处理缓存问题的minify引用里并放置最后,每次发版前修改公共minify_version.js(如写入一条注释或发版日期,只要改变文件内容即可),这样在使用gulp处理时可自动为此类型的引用添加版本号。
二。安装配置gulp环境
1 安装node.js https://nodejs.org/en/
node -v查看安装的nodejs版本,出现版本号,说明刚刚已正确安装nodejs。
npm -v查看npm的版本号,npm是在安装nodejs时一同安装的nodejs包管理器
(安装cnpm 代替 npm*
npm(node package manager)nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等)
但是因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常, cnpm“这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。”;
npm install cnpm -g –registry=https://registry.npm.taobao.org;
- 安装gulp插件(新建个gulptest目录,命令行切换到此目录,然后顺序执行)
cnpm install gulp -g
cnpm install –save-dev gulp
cnpm install –save-dev gulp-rev
cnpm install –save-dev gulp-rev-collector
cnpm install –save-dev run-sequence
cnpm install –save-dev gulp-convert-encoding
3.修改gulp插件的index.js配置文件:
详见后续附录1
- gulptest目录下新建package.json,他是基于node.js必不可少的配置文件
详见后续附录2
5.编写gulpfile.js任务文件,修改为js文件类型放到gulptest目录下(项目使用的gulpfile.js,可根据具体项目修改里面路径即可)
详见后续附录3
6.DOS命令行切换到gulptest目录下,执行gulp,观察结果。
三。 GULP处理后的效果:
非MINIFY类型利用GULP给静态文件链接加上版本号效果:
无版本号的引用:
gulp添加版本号后的引用:
MINIFY类型利用GULP给静态文件链接加上版本号效果:
无版本号的引用:
添加版本号后的引用:
备注:
Css和静态图片的处理方式和js类似,不再详述。
********************************************************** 附录1 **********************************************************
一。更改gulp-rev和gulp-rev-collector(重要,不配置版本号不是加到?后面)
1.打开node_modules\gulp-rev\index.js
第144行 manifest[originalFile] = revisionedFile;
更新为: manifest[originalFile] = originalFile + ‘?v=’ + file.revHash;
2.打开nodemodules\gulp-rev\nodemodules\rev-path\index.js
10行 return filename + ‘-’ + hash + ext;
更新为: return filename + ext;
3.打开node_modules\gulp-rev-collector\index.js
31行if ( !_.isString(json[key]) || path.basename(json[key]).replace(new RegExp( opts.revSuffix ), ” ) !== path.basename(key) ) {
更新为: if ( !_.isString(json[key]) || path.basename(json[key]).split(‘?’)[0] !== path.basename(key) ) {
二。避免多次执行后加上多个版本号
- 打开 node_modules\gulp-rev-collector\index.js 115 行
regexp: new RegExp( ‘([\/\\\’”])’ + pattern, ‘g’ ),
更新为 regexp: new RegExp( ‘([\/\\\’”])’ + pattern+’(\?v=\w{10})?’, ‘g’ ),
三。新增一个pwd_base参数,使其生成json文件时可以指定前缀(用于区分不同文件夹下相同文件名问题)
1.修改node_modules\gulp-rev\index.js,搜索,新增一个pwd_base参数,用于设置根目录
opts = objectAssign({
path: ‘rev-manifest.json’,
merge: false,
// Apply the default JSON transformer.
// The user can pass in his on transformer if he wants. The only requirement is that it should
// support ‘parse’ and ‘stringify’ methods.
transformer: JSON,
pwd_base:” //增加根目录前缀,避免不同路径下同名文件版本号相互覆盖,wangwei 20170308
}, opts, pth);
2.修改node_modules\gulp-rev\index.js,搜索下列代码,新增originalFile = opts.pwd_base + originalFile;行
return through.obj(function (file, enc, cb) {
// ignore all non-rev’d files
if (!file.path || !file.revOrigPath) {
cb();
return;
}
var revisionedFile = relPath(file.base, file.path);
var originalFile = path.join(path.dirname(revisionedFile), path.basename(file.revOrigPath)).replace(/\\/g, '/');
originalFile = opts.pwd_base + originalFile; //新增行 wangwei 20170308
//manifest[originalFile] = revisionedFile;
manifest[originalFile] = originalFile + '?v=' + file.revHash;
cb();
}
********************************************************** 附录1 **********************************************************
********************************************************** 附录2 **********************************************************
{
“name”: “test”,
“version”: “1.0.0”,
“description”: “This is for study gulp project !”,
“homepage”: “”,
“repository”: {
“type”: “git”,
“url”: “https://git.oschina.net/xxxx”
},
“author”: {
“name”: “surging”,
“email”: “surging2@qq.com”
},
“license”: “ISC”,
“devDependencies”: {
“gulp”: “^3.9.1”,
“gulp-bom”: “^1.0.0”,
“gulp-cheerio”: “^0.6.2”,
“gulp-concat”: “^2.6.1”,
“gulp-convert-encoding”: “^1.0.0”,
“gulp-less”: “^3.0.0”,
“gulp-replace”: “^0.5.4”,
“gulp-rev”: “^7.1.2”,
“gulp-rev-collector”: “^1.1.1”,
“gulp-uglify”: “^2.0.1”,
“run-sequence”: “^1.2.2”
}
}
********************************************************** 附录2 **********************************************************
********************************************************** 附录3 **********************************************************
/**
* wangwei 20170307
* 自动生成jsp文件中引用的的js,css文件的版本号,解决客户端缓存问题
*/
//引入gulp和gulp插件
var gulp = require(‘gulp’),
runSequence = require(‘run-sequence’),
rev = require(‘gulp-rev’),
convertEncoding = require(‘gulp-convert-encoding’),
revCollector = require(‘gulp-rev-collector’);
//定义项目文件跟目录(修改为自己的)
var projectRootPath = ‘D:/MyEclipse8.5/Workspaces/CfgWebModule2017/WebContent’;
//定义css、js文件路径,是本地css,js文件的路径,可自行配置
var cssUrl = projectRootPath+’/*/.css’,
minifyCssVersionUrl = projectRootPath+’/css/minify_version.css’,
jsUrl = projectRootPath+’/*/.js’, //非minify方式引用的js文件
minifyJsVersionUrl = projectRootPath+’/js/minify_version.js’; //控制minify方式引用的js文件是否更新(发版前往此文件中写入一条注释即可,注释内容随意,每个/min方式最后加上对此js文件的引用)
//CSS生成文件hash编码并生成
gulp.task(‘revCss’, function(){
return gulp.src(cssUrl)
.pipe(rev())
.pipe(rev.manifest(‘rev-manifest-css1.json’,{pwd_base:’<%=request.getContextPath()%>/’}))
.pipe(gulp.dest(‘rev/css’));
});
//CSS生成文件hash编码并生成 minify 方式
gulp.task(‘revMinifyVersionCss’, function(){
return gulp.src(minifyCssVersionUrl)
.pipe(rev())
.pipe(rev.manifest(‘rev-manifest-css2.json’,{pwd_base:’css/’}))
.pipe(gulp.dest(‘rev/css’));
});
//js生成文件hash编码并生成
gulp.task(‘revJs’, function(){
return gulp.src(jsUrl)
.pipe(rev())
.pipe(rev.manifest(‘rev-manifest1.json’,{pwd_base:’<%=request.getContextPath()%>/’}))
.pipe(gulp.dest(‘rev/js’));
});
//js生成文件hash编码并生成 minify 方式
gulp.task(‘revMinifyVersionJs’, function(){
return gulp.src(minifyJsVersionUrl)
.pipe(rev())
.pipe(rev.manifest(‘rev-manifest2.json’,{pwd_base:’js/’}))
.pipe(gulp.dest(‘rev/js’));
});
//jsp更换css、js文件版本 (此处测试只替换项目涉及到订单页面的几个jsp文件)
gulp.task(‘revJsp’, function () {
return gulp.src([‘rev//.json’, projectRootPath+’//orderEdit_body.jsp’]) /源文件路径*/
.pipe(convertEncoding({from:’GBK’,to: ‘utf-8’})) //项目中jsp文件时utf-8编码的注释掉此行
//.pipe(replace(“<%=request.getContextPath()%>”,”E:/gulpTest/dest/jsp”)) //替换为真实路径
//.pipe(replace(“,/js/”,”,/minify/js/”)) //minify里文件版本号处理
//.pipe(replace(“,/order/”,”,/minify2/order/”)) //minify里文件版本号处理
.pipe(revCollector())
//.pipe(replace(“,/minify/js/”,”,/js/”)) //minify里文件版本号处理
//.pipe(replace(“,/minify2/order/”,”,/order/”)) //minify里文件版本号处理
//.pipe(replace(“E:/gulpTest/dest/jsp”,”<%=request.getContextPath()%>”)) //替换为真实路径
.pipe(convertEncoding({from:’utf-8’,to: ‘GBK’})) //项目中jsp文件时utf-8编码的注释掉此行
.pipe(gulp.dest(projectRootPath+’/’)); /输出路径/
});
//开发构建
gulp.task(‘dev’, function (done) {
condition = false;
runSequence(
[‘revCss’],
[‘revMinifyVersionCss’],
[‘revJs’],
[‘revMinifyVersionJs’],
[‘revJsp’],
done);});
gulp.task(‘default’, [‘dev’]);
********************************************************** 附录3 **********************************************************
备注:
如果输入node -v,或npm -v或gulp提示不是外部命令,确认下用户环境变量PATH中是否有此命令的输出内容
npm config get prefix
确认全局环境变量path中是否有nodejs的安装路径
//下面是一些备忘参考信息,实际应用上面的部分就够了
/******************************************************实际项目应用中需要解决的问题(备忘用,实际应用上面的部分就够了):******************************************************/
源文件路径
js
orderConfig.js
order
order/edit
orderEdit_body.jsp(src指向js/orderConfig.js)
order/edit/sub
orderEdit_body.jsp(src指向order/edit/sub/js/orderConfig.js)
order/edit/sub/js
orderConfig.js
order/edit/std
orderEdit_body.jsp(src指向order/edit/std/js/orderConfig.js)
order/edit/std/js
orderConfig.js
不同路径下相同文件名的问题,若直接生成,则所有引用orderConfig.js的版本号都一样,取的都是js/orderConfig.js的hash值
查看生成的rev\js\rev-manifest.json文件发现虽然为不同文件生成了不同的版本号
“js/orderConfig.js”: “<%=request.getContextPath()%>/js/orderConfig.js?v=4246752bdb”,
“order/edit/std/js/orderConfig.js”: “<%=request.getContextPath()%>/order/edit/std/js/orderConfig.js?v=6123c4e86d”,
“order/edit/sub/js/orderConfig.js”: “<%=request.getContextPath()%>/order/edit/sub/js/orderConfig.js?v=359a924f33”,
但是因为jsp中引用时src都带有<%=request.getContextPath()%>,所以导致没有严格符合json的匹配项,进而匹配替换时可能使用最短的路径给覆盖了
(
)解决方法:
生成rev\js\rev-manifest.json文件时统一加上前缀<%=request.getContextPath()%>,使其匹配jsp中的src能够找到完全匹配项,新增参数方法见下面。
参数使用方法如下:
gulp.task(‘revJs2’, function(){
return gulp.src(jsUrl)
.pipe(rev())
.pipe(rev.manifest(‘rev-manifest1.json’,{pwd_base:’<%=request.getContextPath()%>/’})) //指定前缀,并指定生成的json文件名称
.pipe(gulp.dest(‘rev/js’));
});新生成的rev-manifest1.json如下,重新gulp,这样就解决了不同文件夹下相同文件名的问题.
“<%=request.getContextPath()%>/js/orderConfig.js”: “<%=request.getContextPath()%>/js/orderConfig.js?v=4246752bdb”,
“<%=request.getContextPath()%>/order/edit/std/js/orderConfig.js”: “<%=request.getContextPath()%>/order/edit/std/js/orderConfig.js?v=6123c4e86d”,
“<%=request.getContextPath()%>/order/edit/sub/js/orderConfig.js”: “<%=request.getContextPath()%>/order/edit/sub/js/orderConfig.js?v=359a924f33”,
2.解决jsp文件中minify类型的src引用问题(这样不行,minify的版本号只能加到最后一个js文件上,可根据这个方法简单改造下)。
1651

被折叠的 条评论
为什么被折叠?



