对于前端开发来说,经常要面对JS,CSS,图片等资源的缓存更新问题(CDN永久缓存的就另当别论)。
大部分情况,为了节省服务器压力及带宽且又不失可维护性,习惯对这些资源文件添加比较久的缓存时间,这样就给前端开发人员带来一个自动更新的棘手问题。
其实,较简单的解决办法,就是固定周期或有条件的或每次(这样要缓存何用?)的增加随机数击穿缓存,强制更新即可。
这里说一个也较为简单的方式,利用AJAX的访问来更新本地缓存。
原理很简单,使用http协议的 If-Modified-Since 和 Cache-Control 两个header头参数即可。
脚本举例:
var xhr = false; try { xhr = new XMLHttpRequest(); } catch(e1) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e2) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { xhr = false; } } } if (xhr) { xhr.open('GET', '要缓存的资源文件地址'); xhr.setRequestHeader('If-Modified-Since', '0'); xhr.setRequestHeader('Cache-Control', 'no-cache'); xhr.send(); }
当然,这种做法有一个显而易见的局限性,就是不能跨域更新。
不过换个思路也可以简单解决,把这个更新服务脚本分别部署到有需要的资源文件服务器上即可。
就如腾讯,微博里就很多在这样使用。
腾讯的更新服务页面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>更新文件--Ptlogin</title> <script> function cleanCache(f){ var xmlHttp = false; try { xmlHttp = new XMLHttpRequest(); } catch (trymicrosoft) { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (othermicrosoft) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { xmlHttp = false; } } } if (!xmlHttp){ alert("请按F5刷新页面"); return; } xmlHttp.open('GET', f); xmlHttp.setRequestHeader('If-Modified-Since', '0'); xmlHttp.setRequestHeader('Cache-Control', 'no-cache'); xmlHttp.send(); } if (location.hash){ //var file = location.hash.substring(1,location.href.length); var file = location.href.substring(location.href.indexOf("#")+1, location.href.length); cleanCache(file); } </script> </head> <body> </body> </html>
使用上,很明显,利用IFRAME去访问此页面即可。而部署,则会将此文件复制多份,部署在需要更新的资源服务器对应目录内。