页面的缓存到底应该怎么做?

最后更新:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

赶巧不巧,正好在假期第一天遇到了修改接口地址的问题 —— 节前最后一个工作日后端兄弟自己修改了编译后的 Js 文件中的接口地址,但是并没有生效,只不过当时没发现,今天电话过来问应该怎么处理,奈何电脑没带在身边,只能让他修改了接口地址之后重新编辑被修改的 Js 文件名中的 hash 值随便改一位,同时修改一下 index.html 中的引入路径。
可是没多久又发来消息说,不行还是请求旧地址,没有被修改。我怀疑是页面被缓存了,于是让他确认了一下页面源代码中是否有 no-cachemeta ,他说有,但是页面还是被缓存了,看到引入 Js 文件的路径还是他修改前的旧路径。
于是我就纳闷了,好像浏览器跳过了设置的机制,并没有重新请求服务器获取最新的 index 文件。

正常来说,前端为了加快页面加载,只会在 index.html 页面的 <meta> 中设置 不缓存,而其他类型的资源文件再HTTP服务上设为一个缓存时间,从而加快首屏加载速度。
如果资源文件有变动则通过修改资源文件路径的 hash 值来让浏览器认为是新文件,从而重新请求服务器获取最新的资源。

  • 其实都需要在 HTTP Server 上配置缓存策略,这个配置项贴在文章末尾。

所以遇到这个问题的时候我是很懵逼的,我很早之前就已经给 HTML 页面添加上了不缓存的 <meta> 头,当时自测的时候是正常的。就一边翻文档一边写DEMO,不论怎么做都一直复现不了,实在是研究不好了,又问了一下后端兄弟,答:客户使用的微信打开的链接。 ,他暂时先改了一下把页面重定向到了二级目录解决了问题。

所以问题其实是因为微信内置的X5浏览器,马上去微信社区找了一下,果然!一下就找到了,微信公众号页面缓存问题 | 微信开放社区

大概反馈如下:

  • x5内核好像没有协商缓存

  • 点刷新就访问到新的网页了,第二次进来又是旧的

微信内置的浏览器他不按套路出牌啊,没有协商缓存的同时为了加快访问速度还直接给你缓存了页面。所以之前可能是后端小伙伴没有去配置HTTP服务的不缓存,结果用户访问了页面被缓存起来了。
一般来说服务器端后续把不缓存的配置添加上就好了,结果后期添加上了不缓存的响应头还是没有办法获取到最新的 HTML 入口文件。暂时没有什么好的解决办法了,后端小伙伴已经暂时解决了就先不管了。

🎈 其它问题

1. HTML的 <meta> 标签中设置了不缓存,后端返回头中设置了缓存时间页面会缓存吗?

会被缓存,理论上应该是 Response Headers 的优先级更高。

Meta tags are easy to use, but aren’t very effective. That’s because they’re only honored by a few browser caches, not proxy caches (which almost never read the HTML in the document).
译: meta 标签很容易使用,但并不十分有效。这是因为它们只被少数浏览器的缓存所尊重,而不是代理缓存(几乎从不读取文档中的HTML)。

详情可以参看这个问答 HTML页面 中设置了不缓存,后端返回头中设置了缓存时间页面会缓存吗?

2. HTML的 <meta> 的不缓存设置的应用范围?

HTML 页面中的 <meta> 信息头只会应用在当前 HTML 页面的请求头上,并不会影响 HTML 页面发起的其他 HTTP 请求


✨ Update - 07/03/2024

隔了那么多年,才发现之前的笔记中没有完整的描述好应该如何配置项目的缓存,除了在页面的 meta 头中配置 Cache-Control(其实并没有多少作用)。

更重要的是在服务器的 HTTP Server 中配置缓存规则。那么,简单的用 Nginx 的配置来举例:

http {
  ...
  server {
    listen      80;
    listen      443;
    server_name localhost;

    location / {
      root        /test/your-dist-path;
      # 开启回退路由适配 History 路由模式
      try_files   $uri $uri/ /index.html;
      index       index.html  index.htm;

      # 静态文件配置不缓存
      location ~* \.html$ {
        add_header  Cache-Control no-store;
        expires     -1;
      }
      # 资源文件配置缓存72小时
      location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 72h;
      }
    }
  }
}

最后记得使用 nginx -s reload 让 Nginx 重新加载配置文件(重新加载前程序会自动检测配置文件是否正确,如果有错误会提示并且停止应用新的配置文件)。


参考资源

Cache-Control - HTTP | MDN
HTTP 缓存 - HTTP | MDN

http - How do we control web page caching, across all browsers? - Stack Overflow
google chrome - “Cache-Control: max-age=0, no-cache” but browser bypasses server query (and hits cache)? - Stack Overflow
http - What’s the difference between Cache-Control: max-age=0 and no-cache? - Stack Overflow
http - Difference between no-cache and must-revalidate - Stack Overflow
Cache Control Directives Demystified : Palisade
Caching Tutorial for Web Authors and Webmasters - mnot
浅谈浏览器http的缓存机制 - vajoy - 博客园
理解浏览器缓存机制 [ 没事儿 ]

微信服务号H5开发去除缓存方案 Wechat WebCache Killer - 掘金