微信,请不要缓存我的页面

3,625 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

现象

用户通过公众号菜单访问我们的H5页面,当更新了H5的内容后,用户查看到的内容还是原先的内容,即我们原有的H5页面被微信缓存了。

但当我们将链接复制到浏览器中进行访问时,是可以获取到最新的内容的,也就是说这种缓存现象只存在于微信客户端内。

版本号解决方案

提到浏览器缓存,我们就会想到针对cssjsimage等静态资源的缓存,而针对这些缓存内容的更新,我们的一般做法是增加版本号,即改变访问的url路径。如下表所示:

老版本新版本
xxx.js?version=1.0xxx.js?version=1.1

那么微信里可以这样做么?答案是肯定的,我们可以通过更改公众号菜单的访问的路径来达到清除缓存的目的。但因为公众号菜单覆盖到所有用户是有延迟的,所以期间还是会出现部分用户访问到旧的内容。

版本号改进解决方案

既然公众号的菜单覆盖是有延迟的,那我们是不是可以在不改变菜单路径的情况下,而让用户访问到最新的内容呢?答案是增加中间跳转页,即服务端redirect,时序图如下:

image.png

终极解决方案

再深层次的思考下,同样的路径为什么普通的浏览器能获取到新的内容,而微信客户端浏览器确获取到的是缓存的内容呢?这两者有什么区别呢?浏览器缓存内容的标准是什么呢?

带着这个问题去搜索,我们就会发现,当服务端没有明确告诉浏览器不准缓存(no-cacheno-storeExpiresmax-age等),而只是告诉浏览器一些标记信息(ETagModified),允许浏览器缓存时,浏览器每次访问缓存之前是需要先发请求询问服务器该内容是否有变化的,如果有就获取新的内容,如果没有就返回304则可以使用缓存。时序图如下:

1630331188(1).png

但我们的微信确偏偏不发送询问请求,而是任性的使用过期的缓存内容。

那我们该怎么解决呢?从上面的原因中我们可以得到一切的根因是因为服务端没有明确的告诉浏览器不准缓存,所以我们可以通过更改配置来明确的告知浏览器不准缓存内容,这样就可以让用户每次都可以访问到最新的内容了。

Apache Httpd的配置(已验证)
<IfModule mod_expires.c>
#打开缓存
ExpiresActive On
#默认对所有资源缓存600秒
ExpiresDefault M5
</IfModule>
nginx的配置(未验证)
location ~ \.(html|htm)$ {
  root /data/web/kevin;
  add_header Cache-Control no-cache;
}