关于更新发布CSS和JS文件的缓存问题
现如今,浏览器大战下,各个浏览器也是拼了命的提高性能,升级JS解析引擎,更好的处理浏览器的页面缓存,让用户的浏览体验更快,占用更小的PC资源。那么,问题就出现在JS和CSS缓存,甚至页面缓存上。至于浏览器对页面的缓存,我们一般通过在服务端发送页面的时候设置页面的生存期,一般几个小时就能缓解很大的服务器压力,并且,对浏览者来讲,本地页面晚更新几个小时可能问题也不大。但,问题是,如果页面发生了更新,但是该页面链接的JS和CSS文件却被浏览器缓存下来,只有待浏览器重启后才能被删除,甚至有些浏览器重启后也不主动删除JS和CSS的缓存文件。这样页面与JS和CSS文件就可能发生脱节了,从而出现某种异常现象,甚至页面崩溃。更坑爹的现象是,现在用户为了保存自己的工作(娱乐)状态,根本就长时间不关机,当然也不关闭浏览器。从而使得该问题变得更加严重。
这里提供一种简单并且常用的JS和CSS的缓存解决方案。我们看新浪微博的首页。
该页面加载完毕后的头部代码如下(使用Fiirbug等Ajax调试工具打开):
注意上面的每个JS文件和CSS文件都加上了一个时间戳作为版本号。
即
<script type=”text/javascript” src=”{JS文件连接地址}?version=XXXXXXXX”></script>
或
<link rel=”stylesheet” type=”text/css” href=”{CSS文件连接地址}?version=XXXXXXXX”>
因为浏览器缓存的时候是以URL作为存储单位(还记得POST页面的返回按钮的问题吧?),
从而当每次首页的文件发生更新的时候只需要更改上面的版本号,就能提醒浏览器重新下载该文件了。
如果修改了js文件中的js代码,发布代码到线上后。用户的浏览器使用的还是原来js缓存。所以并不会马上生效。
如何才能让浏览器使用最新的js文件呢?
很多人想到的第一反应是,在<script type="text/javascript" src="/js/common.js" ></script>在后面加一个时间戳来解决。这样url地址每次变化,浏览器就会请求服务端的js,而不会使用缓存。
这样是解决了。但是会导致浏览器每次都要去请求服务端的js文件。占用带宽。作为技术,能不能有种更好的办法呢?既能避免用户的浏览器每次去请求服务端获取js文件。又能在发布新的js代码后,能够使用最新的js文件?
据说,在问号后面加版本号,现在很多网站都这么干。加个版本号能够解决问题吗?
网上查询资料,纵观大家的解决思路总结如下:
1、修改js的文件名。我觉得这样很麻烦。造成版本系统的维护困难。不建议。除非是完全ftp。不过每次发布都修改文件名称。的确造成维护的时候很茫然,接手的人看到文件名称变化,会比较难维护
2、路径后面加时间戳或者随机数的方式。
一般都是在html模版中使用一个时间戳或者随机数函数生成一个值。
<script type="text/javascript" src="{{passport_host}}js/common.js?t={{date("Y-m-d")}}" ></script> 今天和明天的值不同了,重新请求服务器。
<script type="text/javascript" src="{{passport_host}}js/common.js?t={{time()}}" ></script> 使用时间戳,每刷新一次html,值都不同。随机数也是一样的
不推荐使用这种方式。
因为这样的方式导致的问题是,每次刷新html,时间戳都是变化的,url就总是唯一的,于是浏览器总是去请求服务端获取js文件,不会使用浏览器本地的缓存。占用带宽,影响速度
3、路径后面加js的版本号。这样是业界比较成熟的做法。
关键是这个版本号,怎么做版本? 难道真的纳入版本系统里面去?不是的。我突然灵感来,想到一种程序员自己控制的办法。
自己主动加时间,如果本次发布,修改了哪几个js文件。那么就在后面加上一个时间点:年月日
如果一天会发布多次对js文件的修改,那么程序员还要精确点。年月日时分秒即可。
如下:
<script type="text/javascript" src="/js/common.js?time=20150518" ></script>
我去看了一下淘宝,发现也是这样一种方式额,不知道对不对?
如下:
15年8月12日补充:
公司有好几千万注册会员,于是第三方应用使用我们网站会员帐号实现在第三方网站登录,需要设计oauth2.0授权的平台,于是需要参考微博的oauth体制。
无意中发现他们的css也是使用年月日来控制
进一步思考:
这种加时间方法是可行。。不是系统生成的时间,不是所有js文件都加。
是不是可以进一步考虑一种办法,用程序来进行开关呢?
自己勾选。如果这个文件修改了。那么就设置为更新。模版中判断,就根据这个开关,把时间戳自动打上去?
不过这样子觉得没必要。因为还没到那么重大。其实初期,完全可以程序手动把日期打上去即可了。
总结思路:
js文件的内容修改了,可以加个t参数表明一下日期,用这个日期来作为版本号,看到日期也能知道是哪天发布的。
没有修改js文件根本就不用修改日期。
实践:
<script type="text/javascript" src="{{passport_host}}js/common.js?t=20150622" ></script>
如果下一次修改了这个js文件,那么发布的时候,就修改日期
<script type="text/javascript" src="{{passport_host}}js/common.js?t=20150628" ></script>
没有修改的js文件,保留原来的值不动即可。