浏览器缓存机制详解

浏览器缓存机制详解

它们其实代表了浏览器在加载网页时,按照先后顺序依次检查的缓存防线。

下面我们将按照这 6 种缓存机制进行梳理,详细讲解它们是什么、何时缓存以及如何清除:


一、浏览器缓存的 6 道防线(按请求命中顺序)

当浏览器发起一个请求时,它会按照以下顺序依次寻找缓存(前面的没命中,才会找下一个):

① DNS Cache(DNS 缓存)

  • 是什么 :网络请求的第一步是将域名(如 www.baidu.com)解析为服务器的 IP 地址。这个解析过程是耗时的,因此浏览器、操作系统、本地路由器等都会缓存解析结果。
  • 何时缓存:浏览器第一次成功解析域名后,会自动将其 IP 缓存在本地一段时间。
  • 如何清除
    • 代码侧 :前端代码无法 直接控制或清除 DNS 缓存。部分 HTML 标签可用于预解析 以加快速度(<link rel="dns-prefetch" href="//example.com">),但不能清除现有缓存。
    • 用户侧 :在 Chrome 浏览器地址栏输入 chrome://net-internals/#dns,点击 "Clear host cache" 可以手动清除。或者在操作系统中刷新(如 Windows cmd 执行 ipconfig /flushdns)。

② Service Worker Cache(离线缓存)

  • 是什么 :如果域名解析完成,请求发出去前,会被 Service Worker(独立于主线程的后台脚本)拦截。这是唯一一个完全由开发者控制的缓存机制,是实现 PWA(渐进式 Web 应用)离线访问的核心。
  • 何时缓存 :完全由开发者编写的 JavaScript 代码决定。开发者可以通过 Cache API 手动拦截请求,将响应存入 Cache Storage。如果 Service Worker 中没命中缓存,请求才会继续往后走。
  • 如何清除
    • 代码侧 :通过 JS 代码调用 caches.delete('cache-name') 或在 Service Worker 更新时主动注销/清理旧版本缓存。
    • 用户侧 :在 DevTools (F12) -> Application -> Service Workers 中点击 Unregister,或在 Cache Storage 面板中手动右键删除。

③ Memory Cache(内存缓存)

  • 是什么:存储在计算机内存(RAM)中的缓存。如果 Service Worker 没命中,浏览器会检查内存缓存。它的读取速度最快,但生命周期最短。
  • 何时缓存 :浏览器自动 决定。它主要缓存当前页面已经下载完毕的资源(如图片、CSS、JS)。甚至如果你在页面里动态创建了一个 <img> 标签,它也会进内存缓存。
  • 特点短期缓存 。一旦你关闭了这个 Tab 页,内存缓存就会被完全释放。在控制台的 Network 面板,你会看到 (from memory cache)
  • 如何清除
    • 代码侧:前端代码无法精确控制或清除,由浏览器内核自动管理。
    • 用户侧 :直接关闭当前的浏览器标签页(Tab)即可释放;或者在 Network 面板勾选 Disable cache(停用缓存)。

④ Disk Cache(磁盘缓存)

  • 是什么:存储在计算机硬盘(硬盘/SSD)上的缓存。它的读取速度比内存慢,但容量大,且生命周期长(跨页面、甚至跨浏览器重启)。
  • 何时缓存 :浏览器根据 HTTP 缓存规则(强缓存/协商缓存) 自动将资源写入硬盘。通常较大的文件、明确设置了可以长期缓存的文件会被放入这里。
  • 特点长期缓存 。控制台的 Network 面板中会显示 (from disk cache)
  • 如何清除:它的管理和清除规则,完全遵循下文的 HTTP Cache 机制。

⑤ HTTP Cache(HTTP 缓存机制)

  • 是什么 :严格来说,Disk Cache 是物理存储位置,而 HTTP Cache 是判断缓存是否有效的规则协议 。它分为强缓存协商缓存 。当浏览器检查硬盘(Disk Cache)时,就是依据 HTTP 规则来判断的。
    • 强缓存 :浏览器检查响应头中的 Cache-Control (如 max-age=3600) 或 Expires。如果没过期就直接用本地硬盘的,根本不向服务器发请求
    • 协商缓存 :如果强缓存过期了,或者设置为 no-cache,浏览器会向服务器发一次请求 ,带上 If-Modified-Since (对应服务器之前的 Last-Modified) 或 If-None-Match (对应服务器之前的 ETag)。服务器比对后,没变化就返回 304 Not Modified,让浏览器继续用本地缓存;变化了就返回 200 和新资源。
  • 如何清除 / 开发者如何避免缓存死角
    • 代码侧 (避免缓存)
      1. 静态资源加 Hash (现代主流) :Webpack/Vite 等构建工具打包时给文件名加哈希(如 app.12345.js),文件内容一变 Hash 就变,浏览器找不到旧哈希文件,就不得不请求新文件。
      2. 设置不缓存请求头 :服务器端(Nginx 等)给 HTML 入口文件设置不缓存:Cache-Control: no-cache, no-store, must-revalidate
      3. Ajax/Fetch 请求加时间戳/随机数fetch('/api/data?t=' + Date.now()),强制每次请求 URL 都不一样。
    • 用户侧
      1. 强制刷新(Ctrl + F5 / Cmd + Shift + R)。
      2. 开发者工具中勾选 Disable cache
      3. 浏览器设置中"清除浏览数据" -> 清除"缓存的图片和文件"。

⑥ BFCache(Back/Forward Cache,往返缓存)

  • 是什么:这是一种极其特殊的缓存机制,专门针对浏览器的**"前进"和"后退"按钮**优化。当用户点击后退时,浏览器不是重新加载页面,而是直接将整个页面在内存中的状态(包括 JavaScript 执行状态、DOM 树结构)"瞬间"完整恢复出来。
  • 何时缓存:当用户离开当前页面(前往新页面)时,浏览器会自动尝试将当前页面存入 BFCache。
  • 如何清除/控制
    • 代码侧 :如果你不希望页面被 BFCache 缓存(例如涉及敏感的实时金融数据),可以通过设置响应头 Cache-Control: no-store 来彻底禁用它。此外,页面上如果存在未关闭的 WebSocket 连接或 IndexedDB 事务,也会阻止浏览器使用 BFCache。前端可以通过监听 pageshowpagehide 事件中的 persisted 属性来感知页面是从 BFCache 恢复的还是重新加载的。

总结

你看到的这 6 种分类是非常标准的浏览器底层架构视角。它涵盖了从你输入 URL 敲击回车,到页面最终呈现的全链路缓存防线:

  1. 先查有没有 DNS 缓存
  2. 请求发出去前,看有没有被 Service Worker 缓存 拦截。
  3. 接着去最快的 Memory Cache (内存) 里找。
  4. 内存没有,再去 Disk Cache (硬盘) 里找。
  5. 在找硬盘缓存时,严格遵守 HTTP Cache (强缓存/协商缓存) 的协议规则。
  6. 如果你点击了后退按钮,直接从特殊的 BFCache 瞬间恢复整个页面。
相关推荐
星栈独行1 小时前
翻完 Pi 源码:它和 Codex、Claude Code 有何不同
开发语言·javascript·人工智能·程序人生
浅水壁虎5 小时前
vue基础(第二章 )
前端·javascript·vue.js
界面开发小八哥5 小时前
界面控件DevExtreme v26.1新版亮点——支持Angular 22
前端·javascript·angular.js·devexpress·ui开发·devextreme
心机之蛙qee5 小时前
Redis的主从、哨兵及集群
数据库·redis·缓存
mONESY6 小时前
React useState 核心原理与最佳实践:从异步更新到性能优化全解
javascript
腻害兔6 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
qq_297574676 小时前
RuoYi框架二次开发系列(五)性能优化、Redis缓存实战、分布式部署、接口限流与安全加固生产方案
redis·缓存·性能优化
gis开发之家7 小时前
《Vue3 从入门到大神37篇》Vue3 源码详解(七):watch 与 watchEffect 源码对比——副作用是如何被追踪的?
javascript·前端框架·vue3·vue3源码
bloglin999998 小时前
langchain 和 langgraph 和 react
javascript·react.js·langchain