Sunday 的面试指南

HTTP 强缓存和协商缓存有什么区别?Cache-Control、ETag 和 304 怎么配合?

🧑‍💻 面试官:浏览器缓存怎么分?

🙋‍♂️ 我:强缓存没过期就直接使用,协商缓存会问服务器有没有变化。

🧑‍💻 面试官:那写 no-cache,是不是就不缓存了?

🙋‍♂️ 我:不是,可以保存,但复用前需要验证。

🧑‍💻 面试官:304 没有文件正文,浏览器从哪里拿页面?如果 HTML 被缓存一年,发了新版本以后怎么办?

先分清「能不能直接复用」和「有没有保存副本」。缓存未必不请求,发起请求也未必重新下载整个文件。

面试速答(60 秒版)

强缓存是浏览器在缓存仍然新鲜时,直接复用已有响应,不需要为了这个资源向服务器验证。常用 Cache-Control: max-age 指定新鲜期。

协商缓存是在需要验证时,带着资源标识询问服务器。例如 ETag 配合 If-None-Match。资源没变返回 304,浏览器使用已保存的正文;资源变了就返回新的 200 响应。

no-cache 不是禁止保存,而是复用前需要验证;no-store 才是要求不要存储这次响应。private 用来限制共享缓存,不是禁止浏览器缓存。

发布时,可以让 HTML 经常验证,让带内容哈希的静态资源长期缓存。新 HTML 引用新文件,而不是要求所有用户清空缓存。

浏览器缓存:直接用,还是先问?

知识点详解:浏览器到底是在判断什么?

有副本以后,还要判断能不能用

首次请求 app.js,服务器返回正文,并附上缓存规则与资源标识。浏览器保存的不只是内容,还有响应头和相关时间信息。

下次访问,首先判断副本是否匹配、是否允许复用,再看它是否仍然新鲜。不能把“磁盘上有文件”当成“任何时候都能直接用”。

新鲜期也不是简单从某个本地文件的修改时间计算。响应的年龄等信息都会参与判断。

需要验证时,带着标识去问服务器

浏览器带什么服务器判断什么后续怎么处理
If-None-Match当前 ETag 是否匹配没变 304,变了返回新正文
If-Modified-Since是否在指定时间后修改根据修改时间决定是否需要新正文

ETag 是服务器给资源表示的校验标识,不一定等于文件 MD5;Last-Modified 是修改时间。用于缓存验证时,两者同时出现,If-None-Match 优先。

304 不传资源正文,浏览器使用已有副本。但这次请求已经发生,网络往返仍然存在。MDN 缓存指南可以核对这些指令与验证规则。

三个名字很像,需求却不同

no-cache 不能理解成“什么都不留”。服务器确认没变以后,旧副本仍然有用。

no-store 要求不要存储这次响应。但它不是远程清空所有旧缓存的按钮,此前已经保存的副本还需考虑。

private 则限制共享缓存,防止同一份个性化响应被发给其他用户。浏览器自己的私有缓存仍然可以按规则保存。

因此,“始终需要验证”“不能留副本”“不能共享”,不是一件事。个人信息、实时状态和静态素材应该分别设计。

新版本怎样让浏览器发现?

不带版本的 HTML 如果长期强缓存,浏览器可能一直不问服务器,自然不知道新版本已经发布。

一种常见方案,是 HTML 使用 no-cache 并提供验证标识;脚本和样式生成带哈希的文件,例如 app.a81f.js,再设置较长的新鲜期。

内容变化,URL 跟着变。新 HTML 引用新地址,就会请求新文件。

发布时还需要保留一段时间的旧资源。旧标签页可能后续才加载某个代码块,如果旧文件被立即删除,就会出现模块加载失败。缓存策略应该与发布策略一起考虑。

新 HTML,引向新资源

面试官继续追问

memory cache 和 disk cache,是另外两种缓存协议吗?

不是。它们描述副本放在哪里;强缓存与协商缓存描述怎样复用和验证。两组概念属于不同层面。

有 ETag,就一定每次返回 304 吗?

不一定。新鲜期内可能不验证,内容变化会返回新正文,请求条件也可能使缓存无法复用。

刷新、强制刷新和后退,行为都一样吗?

不同。它们可能使用不同缓存处理,历史导航还可能从 bfcache 恢复页面快照。基本资源机制不能直接当成所有按钮操作的固定顺序。

面试速记卡

  • 强缓存:副本仍新鲜,可以直接复用。
  • 协商缓存:带标识验证,没变用旧正文,变了拿新正文。
  • 304:省正文,不省验证请求。
  • 指令:no-cache 要验证,no-store 不存储,private 不共享。
  • 发布:入口常验证,哈希资源长期缓存,旧资源适当保留。
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历