一:现象
- 客户端加载过H5页面A,后来H5修改为A'发布之后,在很长一段时间内,客户端一直展示的是A,没有更新为A'。
- 重启之后依然没有更新,只有清除缓存或者重装APP才会更新。
二:分析
根据现象得出,是由于webview的缓存导致页面一直没有更新。但是为什么没有更新?更新的机制是什么?应该怎么修改?
首先看下客户端的缓存机制,CacheMode一共有五种
CacheMode {
// 如果页面没有强制任何特定行为(依赖服务端控制),如果本地有未过期的缓存,就会直接加载本地缓存,否则就请求网络
LOAD_DEFAULT = -1
// 从API 11开始就废弃了,和LOAD_DEFAULT行为一致
LOAD_NORMAL = 0
// 只要本地有缓存,不管有没有过期,都使用本地缓存。否则就请求网络
LOAD_CACHE_ELSE_NETWORK = 1
// 忽略本地缓存(就算有也不用),直接请求网络
LOAD_NO_CACHE = 2
// 只使用本地缓存,不请求网络
LOAD_CACHE_ONLY = 3
}
重点看下LOAD_DEFAULT模式,这个是依赖服务端配置的缓存策略
http协议缓存机制
http协议缓存机制是指通过 HTTP 协议头里的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等字段来控制文件缓存的机制。
Expires 是 HTTP1.0 标准中的字段,Cache-Control 是 HTTP1.1 标准中新加的字段,功能一样,都是控制缓存的有效时间。当这两个字段同时出现时,Cache-Control 是高优化级的。
Cache-Control参数可参考 浅谈http中的Cache-Control
三:解决方案
客户端:CacheMode使用LOAD_DEFAULT即可,依赖服务端控制缓存策略。为了解决线上版本缓存有效期时间过长的问题,可以在请求的url后面加无效参数,例如#,欺骗浏览器url变动,强制浏览器去服务器更新一次。
服务端:修改nodejs express服务,设置静态资源的时候设置了下这个Cache-Control属性。修改方式可参考 Express 中设置缓存Cache-control的maxAge
服务器配置:Nginx服务器配置Cache-Control也是可行的。
缓存策略需要根据具体业务来确定,如果该页面没有要求实时更新,可以使用max-age=XX来控制,在再XX秒时间范围内使用缓存,否则就请求网络。
四:测试流程
使用max-age=60验证页面更新情况
- 前提,清除缓存,服务端先加上max-age属性
- 客户端先进入页面缓存一次。
- h5修改资源发布
- 客户端再60秒之内打开页面,没有更新,60秒之后再次打开,页面正常更新。
五:注意事项
- 如果之前服务端没有加任何控制缓存的参数(Cache-Control),客户端缓存了该H5页面,此时修改服务端缓存策略,客户端在缓存过期之前是不会重新请求资源的。必须等到客户端缓存过期,或者清除缓存才可以。
- HTML头部添加
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
并没有生效,被忽略了
- 在服务端没有配置任何缓存策略时,Android缓存有效期时间会很长,也就是长时间不会更新。而iOS每次进入页面都会更新,由于iOS和Android内核不一样,iOS是Safari,Android是chromium,处理方式可能会有差异。
- 在服务端没有加任何控制缓存的参数情况下,使用pc端浏览器打开H5,在H5修改之后,谷歌浏览器也是没有立即更新的,必须使用强制刷新(Shift+F5),但是火狐浏览器F5就可以正常刷新了。谷歌浏览器和Android内置浏览器都是chromium内核,表现基本一致。
- 查看网页响应头
浏览器打开该网页,按F12,选择Network,然后再刷新下网页,选择左下栏第一个.html的页面,右面的Headers里面可以看到Cache-Control,说明服务端配置生效了。
用心写代码,不辜负程序员之名。