资源版本管理的优化 - 问题分析

  • 作者:KK

  • 发表日期:2016.11.06


  • 提示:如果你的项目是前后端分离开发,前端使用gulp或fis等独立构建的话就一般不会出现这些问题,而后端输出模板并在模板里嵌PHP标签的非前后分离开发就会有这些问题

其实核心问题很简单,浏览器正常情况下只要加载过/a.js的话,那如果再加载就会从缓存里取,不会再次请求服务器

然而当/a.js有修改时,某些情况下还是无法请求服务器获取新的,而是从缓存里面取(这里的原因并不是浏览器有BUG或者服务器有BUG,而是一些中间网络节点的影响)

所以要解决的问题就是用户如何能在我们修改了js的时候,保证他们的浏览器能实时加载到

办法就是让网址变得不同就行了,比如变成/a.js?version=1,然后再换成/a.js?version=2又会再重新加载了

其实这里不止是JS,而是html静态文件、css、图片等都会这样

而其中如果用?version=1这种方案加上CDN缓存的话就存在遭遇CDN攻击的风险,所以我建议改成?version={文件MD5}这样的方式


Yii自带的解决方法

早期的Yii2框架虽然没法解决,但大概在2.0.5版本以后就支持了Assets包输出时间戳作为版本号防止缓存

用法是配置assetsManager组件的appendTimestamp属性为true即可,你会发现register后模板输出的资源是一个带有时间戳作为版本标识的(这个时间戳就是文件的最后修改时间)

但是这里会导致每次输出版本资源都会读文件的修改时间(读文件信息),我则想有更好的效果,就是只更新一次版本号,所以才写了本系列的文章

看上去解决这个问题是有点儿麻烦的事情,但作为一个用心做事的人,我会从方方面面去解决各种遇到的问题,它所带来的好处是一劳永逸的————这是我2015年2月做的事情,那时候Yii2推出还不到半年