browser 与 cache

January 04, 2018 by Sylvenas

HTTP cache 中讲解了 HTTP 缓存相关的知识,我们知道了:

  • Cache-Control 用来控制强缓存(code:200, from memory/disk),
  • Last-Modified/If-Modified-Since 和 Etag/If-None-Match 用来控制协商缓存,决定是(code:304,Not Modified),还是 (code:200, from server)

浏览器的行为(back/forward/refresh)又和 HTTP 缓存怎么互相配合的?

在 single-page app 中的,点击超链接跳转其他的路由,然后点击浏览器的回退和点击超链接回退又有什么区别呢?回来的页面会刷新吗?

实验

三个获取随机 字符串的请求 no-cache,no-store,,Header 分别设计为:

  • /api/test/no-cache:
Cache-Control: must-revalidate, no-cache, private
Pragma: no-cache
Etag: "((the hex value))"
  • /api/test/no-store:
Cache-Control: must-revalidate, no-store, no-cache, private
Pragma: no-store, no-cache
Etag: "((the hex value))"
  • /api/test/no-cache?test=Math.random():
Cache-Control: must-revalidate, no-cache, private
Pragma: no-cache
Etag: "((the hex value))"

最后一个用来破坏缓存,每次都会请求最新的数据

Chrome

浏览器 back

清空缓存:

点击第一个超链接跳转到同源的 other page, 然后点击浏览器的back,回到主页:

得出结论:

  • home page 和 no-cache 接口都被缓存
  • no-store 接口不被缓存,重新触发了请求

点击页面超链接回退

清空缓存:

点击第一个超链接跳转到同源的 other page, 然后点击other page 上的超链接,回到主页:

得出结论:

  • home page 和 no-cache 接口不被缓存,重新触发了请求
  • no-store 接口不被缓存,重新触发了请求

刷新浏览器

清空缓存:

点击浏览器刷新按钮:

得出结论:

  • home page 和 no-cache 接口不被缓存,重新触发了请求
  • no-store 接口不被缓存,重新触发了请求

Safari

浏览器 back

清空缓存:

点击第一个超链接跳转到同源的 other page, 然后点击浏览器的back,回到主页:

得出结论:

  • home page 没有被缓存,触发了新请求,但是所有的接口的都没有触发重新请求
  • no-cache 接口被缓存
  • no-store 接口被缓存

点击页面超链接回退

清空缓存:

点击第一个超链接跳转到同源的 other page, 然后点击other page 上的超链接,回到主页:

得出结论:

  • home page 和 no-cache 接口不被缓存,重新触发了请求
  • no-store 接口不被缓存,重新触发了请求

刷新浏览器

清空缓存:

点击浏览器刷新按钮:

得出结论:

  • home page 和 no-cache 接口不被缓存,重新触发了请求
  • no-store 接口不被缓存,重新触发了请求

结论

  • 可能每种浏览器实现的方式都不一样
  • 但是对于HTML文件的处理,倒是很相似,刷新浏览器还是点击超链接回退,都是会主动请求的(哪怕已经设置了 Cache-Control:max-age:60)

为什么 HTML 文件 都不会使用缓存呢?因为客户端也可以使用 Cache-Control:max-age:0,来强化或者放松对过期时间的限制,有些应用程序对文档的新鲜度要求很高,比如人工刷新按钮,对这些应用程序而言客户端(浏览器会自动放弃缓存从浏览器读取),可以看下 HTML 文件的 Request Header Cache-Control,做验证

参考资料