强缓存和协商缓存-面试必会

本文详细介绍了浏览器的缓存机制,包括强缓存和协商缓存的工作原理,以及HTTP头部Cache-Control、Expires、Last-Modified和ETag的相关知识。强调了强缓存与协商缓存的区别,以及如何设置和优化缓存策略。此外,还探讨了Service Worker、Memory Cache、Disk Cache和Push Cache等浏览器的三级缓存。文章提供了实际应用场景的示例,如设置不同类型的资源缓存策略,并讨论了用户行为对缓存的影响。最后,通过JS实现了一套简单的SWR机制,以实现异步缓存更新。
摘要由CSDN通过智能技术生成

1、关于浏览器缓存 你需要知道的一切

  • 强缓存
    • HTTP/1.0时期使用的是Expires;
    • HTTP/1.1使用的是Cache-Control
  • 协商缓存
    • Last-Modified If-Modified-Since
    • ETag If-None-Match

浏览器缓存分为强缓存和协商缓存
 

本质区别在于 强缓存是不需要发送HTTP请求的, 而协商缓存需要.

就是在发送HTTP请求之前, 浏览器会先检查一下强缓存, 如果命中直接使用,否则就进入下一步。

一、强缓存

是否强缓存主要检查什么

浏览器检查强缓存的方式主要是判断这两个字段:

  • HTTP/1.0时期使用的是Expires;
  • HTTP/1.1使用的是Cache-Control

(expires中文意思有效期, cache-control中文意思缓存管理)

Cache-Control: max-age=300

表示的是这个资源在响应之后的300s内过期, 也就是5分钟之内再次获取这个资源会直接使用缓存.


max-age 可设置强缓存周期,在该周期内将直接从客户端缓存获取资源,而不会向服务器发送请求


 

Cache-Control: max-age=300

表示的是这个资源在响应之后的300s内过期, 也就是5分钟之内再次获取这个资源会直接使用缓存.


 

Expires和Cache-control的对比

  • Expires产于HTTP/1.0,Cache-control产于HTTP/1.1;
  • Expires设置的是一个具体的时间,Cache-control 可以设置具体时常还有其它的属性;
  • 两者同时存在,Cache-control的优先级更高;
  • 在不支持HTTP/1.1的环境下,Expires就会发挥作用, 所以先阶段的存在是为了做一些兼容的处理.

若是设置了Expires, 但是服务器的时间与浏览器的时间不一致的时候(比如你手动修改了本地的时间), 那么就可能会造成缓存失效, 因此这种方式强缓存方式并不是很准确, 它也因此在HTTP/1.1中被摒弃了

[译] 写给大家看的 Cache-Control 指令配置 - 掘金

  • public和private
    • 意味着包括 CDN、代理服务器之类的任何缓存都可以存储响应的副本。public 指令经常是冗余的,因为其他指令的存在(例如 max-age)已经隐式表示响应是可以缓存的
    • 相比之下,private 是一个显式指令,表示只有响应的最终接收方(客户端或浏览器)可以缓存文件。虽然 private 本身并不具备安全功能,但它意在有效防止公共缓存(如 cdn)存储包含用户个人信息的响应。
  • max-age
    • max-age 定义了一个确保响应被视为“新鲜”的时间单位(相对于请求时间,以秒计)。
    • Cache-Control: max-age=60
    • max-age 本身有一个巨坑,它告诉浏览器相关资源已经过期,但没有告诉这个过期版本绝对不能使用。浏览器可能使用它自己的机制来决定是否在不经验证的情况下释放文件的过期副本。这种行为有些不确定性,想确切知道浏览器会怎么做有点困难。为此,我们有一系列更为明确的指令,用来增强 max-age
      • s-maxage(注意 max 和 age 之间没有 -)会覆盖 max-age 指令,但只在公共缓存中生效。max-age 和 s-maxage 结合使用可以让你针对私有缓存和公共缓存(例如代理、CDN)分别设定不同的刷新时间。
  • no-store
    • no-store 是一个非常高优先级的指令,表示不会将任何信息持久化到任何缓存中,无论是私有与否。任何带有 no-store 指令的资源都将始终命中网络,没有例外。
  • no-cache
    • 它意味着“在你和服务器验证过并且服务器告诉你可以使用缓存的副本之前,你不能使用缓存中的副本”。没错,听起来应该叫 must-revalidate!不过其实也没听起来这么简单。
    • 事实上 no-cache 一个可以确保内容最新鲜的非常智能的方式,同时也可以尽可能使用更快的缓存副本。no-cache 总是会命中网络,因为在释放浏览器的缓存副本(除非服务器的响应的文件已更新)之前,它必须与服务器重新验证,不过如果服务器响应允许使用缓存副本,网络只会传输文件报头:文件主体可以从缓存中获取,而不必重新下载。
    • 所以如我所言,这是一个兼顾文件新鲜度与从缓存中获取文件可能性的智能方式,缺点是它至少会为了一个 HTTP 报头响应而触发网络。
    • no-cache 一个很好的使用场景就是动态 HTML 页面获取。想想一个新闻网站的首页:既不是实时的,也不包含任何敏感信息,但理想情况下我们希望页面始终显示最新的内容。我们可以使用 cache-control: no-cache 来让浏览器首先回访服务器检查,如果服务器没有更新鲜的内容提供(304),那我们就重用缓存的版本。如果服务器有更新鲜的内容,它会返回(200)并且发送最新的文件。
    • 提示:max-age 指令和 no-cache 指令一起发送是没用的,因为重新验证的时间限制是零秒。
  • must-revalidate
    • Cache-Control: must-revalidate, max-age=600 must-revalidate 需要一个关联的 max-age 指令;上文我们把它设置为 10 分钟。
    • 如果说 no-cache 会立即向服务器验证,经过允许后才能使用缓存的副本,那么 must-revalidate 更像是一个具有宽期限的 no-cache。情况是这样的,在最初的十分钟浏览器不会(我知道,我知道......)向服务器重新验证,但是就在十分钟过去的那一刻,它又到服务器去请求,如果服务器没什么新东西,它会返回 304 并且新的 Cache-Control 报头应用于缓存的文件 —— 我们的十分钟再次开始。如果十分钟后服务器上有了一个新的文件,我们会得到 200 的响应和它的报文,那么本地缓存就会被更新。
    • must-revalidate 一个很适合的场景就是博客(比如我这个博客):静态页面很少更改。当然,最新的内容是可以获取的,但考虑到我的网站很少更改,我们不需要 no-cache 这么下重手的东西。相反,我们会假设在十分钟内一切都好,之后再重新验证。
    • proxy-revalidate
      • 和 s-maxage 一脉相承,proxy-revalidate 是公共缓存版的 must-revalidate。它被私有缓存简单地忽略掉了。
  • immutable
    • immutable 是一个非常新而且整洁的指令,它可以把更多有关我们所送出文件类型的信息告知浏览器
    • 如果服务器上有一个更新鲜的内容可用,我们当然想下载它。这样我们将得到一个 200 响应,一个新文件,并且 —— 希望是 —— 问题已经修复了。而如果服务器上没有新文件,我们将返回 304 报头,没有新文件,只有整个往返请求的延迟。如果我们重新验证了大量文件且都返回 304,这会增加数百毫秒的不必要开销。
    • immutable 就是一种告诉浏览器一个文件永远都不会改变的方法 —— 它是不可变的 —— 因此不要再费心重新验证它。我们可以完全减去造成延迟的往返开销。那我们说的一个可变或不可变的文件是什么意思呢?
    • style.css:当我们更改文件内容时,我们不会更改其名称。这个文件始终存在,其内容始终可以更改。这个文件就是可变的。
    • style.ae3f66.css:这个文件是唯一的 —— 它的命名携带了基于文件内容的指纹,所以每当文件修改我们都会得到一个全新的文件。这个文件就是不可变的。
    • 如果我们能够以某种方式告诉浏览器我们的文件是不可变的 —— 文件内容永远不会改变 —— 那么我们也可以让浏览器知道它不必检查更新版本
  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值