老旧的项目,日复一日的缝缝补补,没有大的动荡,其实一直维持着原有的样子也是能够的...html
不过就这样子的话也太没意思了。前端
眼看着当前各类炫酷的框架操做,好生羡慕,旧项目积重难返,但内心却早已种草《大公司里怎样开发和部署前端代码》,想动手实现一番。文章里的思路,在评论里有人指出 Ruby on Rails 其实早就有这样的实现了,即 Asset Pipeline,这两均可以拜读一番。node
趁着手上工做告一段落,暂时有空闲时间,跟后端小伙伴商量着怎么处理这个缓存问题,因每次发版都会引起缓存问题,运营人员、用户每次都要强刷,确实蛋疼。webpack
期间找了现有的方案,找来找去仍是百度出的 fis 知足一切需求,可是项目已经停滞了许久,便做罢。后面想着与其这样动找西找的,不如本身动手拼凑个!!!git
经过上述暴露的问题,就着手一个一个拆分解决了。github
针对第一个问题,后端经过修改原有的加载方式,在加载的时候都去读取由前端这边生成的资源表,匹配资源,在表上的就替换上去,不在的就回退到备用(原有)的资源那边。web
能够看到关键词:资源表、匹配、替换,确定不多是人肉去搞这个了,这样神都救不了你。项目自己使用的 gulp
去作一些重复的操做的(压缩、混淆、复制搬运这些),那就继续在这上面捣鼓好了(webpack只是浅尝辄止)。chrome
这个能够经过 gulp-rev
和 gulp-rev-collector
插件来生成、替换内容,因学艺不精因此里面有些是人肉写的,未经过插件去实现。npm
生成文件指纹:gulp
借助于 node
的 crypto
模块,咱们能够经过如下方式简单的了解下指纹的生成(代码来自 npm 包插件:rev-hash):
'use strict'; const crypto = require('crypto'); module.exports = input => { if (typeof input !== 'string' && !Buffer.isBuffer(input)) { throw new TypeError('Expected a Buffer or string'); } return crypto.createHash('md5').update(input).digest('hex').slice(0, 10); };
喏,这就是指纹生成啦。
指纹的生成简单,可是替换上就比较麻烦了,由于路径都是写在后端模板内的,你前端也操做不了。因此这里就须要生成资源表给到后端,后端经过读取该资源表去匹配替换了。
后端处理好该问题,那么上述的第2、第3、第四的问题也就解决了。后端发版时,拉取新的资源表便可,无需再去手动修改版本号,前端能够更好的控制资源了。
由于项目中用到了 requirejs
,因此其配置文件也须要替换,没有用到 gulp-rev-collector
,人肉简单的使用了 replace
方法去替换资源表上的内容。
期间就遇到这样的问题:每次更新资源时,删除整个版本目录,生成新的版本资源仍是保留原有资源,生成新的资源。
整个删除(覆盖式发布):在资源发版后会有短暂的资源找不到的问题(有可能来不及刷新资源表),可是好处是不会有冗余的文件存在。
保留旧文件,生成新文件(非覆盖式发布):随着时间的推移,版本化的文件内容会日积月累,变得越发庞大,单是咱们这边设想的起码保留3+1份(上上次、上次、当前 + 回退用的未版本化的文件)。
固然,为了不前者带来的短暂问题,咱们选择了后者,经过定时任务去清理过时文件(git 从新拉取到本地的话,全部文件的建立时间、修改时间、访问时间都是同样的,因此不能在本地对其进行操做)。
上面有提到过该问题,咱们采用的重命名文件的形式,为何不使用附带查询字符串的形式呢?
其实前面的知乎大神已解释了该缘由,《高性能网站建设指南》的做者也在书中提到了,这是他博文上的观点:Revving Filenames: don’t use querystring,博文是10年前的了...10年前的...10年前...10年...10...1...。
经过查看 chrome
的 network
面板,能够看到 size
栏显示了第二次访问的资源,有些显示的是 from memory cache,有些则是 from disk cache,status
栏显示的状态码都是 200
而在 firefox
下显示的倒是 304
已缓存的状态,这又是为何呢?