###背景 前端页面中,静态文件的缓存可以加快网站的响应,但是开发人员如果修改js、css后直接发布线上,用户短时间内看到的依然是老的样式。访问最新的静态资源一般是两种
1. 强制刷新2. 在修改的静态文件后面加上后缀比如时间戳等
显然第一种需要用户主动强刷页面,在pc端通过ctrl+f5勉强可以,但在移动端却要清理缓存数据了,显然不太友好 对于第二种,不需要用户手动刷新,但是对于开发人员则需要每次手动加一个时间戳,也比较浪费时间,接下来我有一种方法供大家参考
利用前端构建工具Gulp来协助完成 Gulp的安装就不赘述,网上一大把
通常前端尤其是移动端为了减少http请求提高响应速度都会压缩js、css静态资源,在前端页面中引用压缩后的代码如 <script src = "/clientwebview/js/build/detail.js"></script>
是一个一般的写法,加了时间戳后,就变成 <script src = "/clientwebview/js/build/detail.js?20150126"></script>
这样,整个流程就是
压缩文件、加时间戳
让我现在尝试用gulp把这个流程简化为一个步骤,这其中需要做的事情有
- 自动监听更新的源文件
- 自动重新压缩、合并源文件为待上线文件
- 自动为所有引用到这个文件的链接加上标识(这里用md5、也可以用时间戳或其他)
###代码 基于以上,生成的代码如下
var gulp = require('gulp');var concat = require('gulp-concat');var uglify = require('gulp-uglify');var watch = require('gulp-watch')var md5 = require("md5-file");//根据摘要生成md5var replace = require('gulp-replace')//替换文件中的文本var fs = require('fs'); //文件系统var versionFile='./version.log' //用来写入,每次版本更新的记录// Rerun the task when a file changesgulp.task('watch', function () { //原文件更新 watch(['../js/common/**/*.js'], ['test']); //观察编译后的文件更新 watch('../js/build/*.js', function () { var localFilePath = arguments[0].history[0];//获取修改的本地文件名 var fileMd5 = md5(localFilePath) //获取文件md5 var fileName = localFilePath.match(/([^\\]+?(js|css))/g)//得到文件名 //全文检索fileName,用到的地方就加一个时间戳md5 console.log('===========', localFilePath, fileName, fileMd5) var now = new Date() var d = now.toISOString() var content = '【'+d+'\t'+fileMd5+'\n'+localFilePath+'】\n' fs.appendFile(versionFile,content) //将这个文件的md5写到文件中,方便查看 var js_r = new RegExp('(
简单说明下,
首先是依赖,都是需要手动下载的 如replace,下载本地就是
npm install gulp-replace --save-dev
代码大致意思,定义一个watch的任务,监听 ['../js/common/**/*.js'] common下所有js文件的修改,如果修改,则执行任务test,之后打包到build目录下,第二个watch监听到文件变化,遍历所有文件,查找引用的地方,并加上md5 hash值。现在交给我们的任务就是一条命令了 gulp watch
###效果 可以看到,执行命令后,我手动修改了源码,然后压缩后的detail.js更新了,然后就去找所有文件有引用的地方,都替换成这个md5,我截图的只有一个地方,其实更新了几十个文件 同时 versionFile也会写入一条记录,对应时间、md5、文件 同理,css样式也可以仿照
###遗留的需要改进的地方 正则匹配的仅仅是文件名,如果不同路径下相同文件名,也会匹配到。中间需要多加一个校验的操作,即
判断修改的文件 与 正则匹配的文件 是否是同一个文件。