HTML5游戏和APP缓存与版本更新
概述
浏览器的缓存可以说是一把双刃剑,一方面可以大大加速用户访问的速度,节约带宽;另一方面在版本更新时,缓存又是一个头疼的问题,浏览器有可能使用缓存而非最新发布的资源。资源包括js脚本、CSS、图片资源等。
使用HTML5开发App或者游戏时,理想状态应该是这样的:用户第一次访问,下载和缓存资源;再次访问时,如果服务器版本没有更新,继续使用缓存的资源,不用重新下载;如果服务器版本有更新,则下载更新的资源,然后进入App/游戏。
HTTP的If-Modified-Since Header可以方便的检查文件是否有更新,我们只需要在服务器配置支持If-Modified-Since Header。nginx默认开启,apache需要手动配置一下。没有更新的文件,服务器返回304,但不会传输文件内容,所以请求返回会非常快;有更新的文件,返回200,并传输文件内容。
实际上,对于js脚本、CSS、文本、JSON等文件,可以使用XMLHTTPRequest下载,大部分浏览器会自动进行If-Modified-Since判断,所以这一部分的版本更新和缓存通常是没有问题的;而对于图片资源,XMLHTTPRequest不能加载Cross-domain的图片,而且只能加载Base64格式图片,会使图片尺寸大幅增加。当然,也可以考虑使用XHR2,或者其他XHR的增强,但是兼容性都还不是特别的好。通常情况下我们使用HTML5的Image元素,设置src属性的方式下载图片资源,但会直接使用缓存的资源。
那么问题来了,怎么确保图片资源的缓存和版本更新没有问题呢?(我使用的测试浏览器包括PC端的Chrome/Firefox/Safari,移动端的Safari/Chrome/微信浏览器/QQ浏览器,其余平台未经测试,本文给出方案在其余浏览器仍需测试验证。)
方案1:直接更改图片资源的访问地址
简单粗暴但是十分有效的方法,每次版本更新之后将更新图片的访问地址直接改变。可以在访问地址后加参数,也可以根据文件的MD5值更改文件名,推荐直接改文件名。需要做的工作就是写脚本自动计算MD5值,更改文件名,在js/html等文件里访问地址也需要自动搜索替换,一键发布,搞定。
不足之处:某些js脚本可能有拼接生成文件访问地址的,例如某个特效序列帧,访问地址为"assets/effect_{0}.png".format(index),这种情况替换就会比较麻烦,需要特殊考虑。(此处我修改了String.prototype.format)
方案2. 使用HTML5的ApplicationCache
ApplicationCache我在之前的博文也有介绍,版本更新时我们只需要对应manifest文件的版本号和CACHE列表即可,浏览器会自动根据manifest文件列表更新文件,始终能保证用户访问到的资源都是最新的。写脚本自动生成manifest文件,一键发布,搞定。
不足之处:如果图片资源很大,我们不希望用户下载所有的图片才进入App/游戏,有很多图片资源可以进入后按需加载。那么这部分按需加载图片就要列入NETWORK列表,或者为了简便直接设置NETWORK: *。问题在于,HTML5规范中NETWORK段是从来不进行缓存的,那么用户再次访问时,按需加载图片资源需要重新下载。所以如果存在按需加载的图片资源,ApplicationCache效果就差很多。
实际测试中,微信浏览器/QQ浏览器对于NETWORK段的资源并没有遵循规范,也进行了缓存,即使用户退出再次访问,按需也会使用缓存的图片,加载速度很快。所以ApplicationCache方案在这两个浏览器就非常适合。Safari/Chrome则不会对NETWORK段资源缓存。
方案3:在服务器配置图片资源的expire时间
第三种思路则是在服务器返回请求时控制图片资源的expire时间,大部分浏览器在文件expire时间到了之后重新从服务器请求下载文件(微信浏览器/QQ浏览器例外,经测试即使expire之后依然会使用缓存图片。。)。我们的App/游戏依然使用浏览器的普通缓存而非ApplicationCache,测试中发现expire后浏览器请求下载文件支持If-Modified-Since,所以只要始终标记图片资源为expired,浏览器就可以自动检查图片是否需要更新。这种方案设置简单,但是非常有效。
比如nginx设置:
location ~* \.(jpg|jpeg|png|ico)$ { expires -1; }
不足之处:在Safari/Chrome的效果非常好,但在对于部分缓存机制比较强的浏览器(微信/QQ浏览器等),这种方案不可行。
总结
以上的方案是我在不停的摸索中总结出来的,但概括来说,缓存和版本更新问题,并没有找到一个完美的通用解决方案,浏览器实现和支持HTML5程度千差万别,还是需要根据发布的平台对应选择方案。如果您有更好的方案,欢迎交流和分享!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。