2553 字
13 分钟
浏览器缓存

一、为什么需要浏览器缓存?#

1.1 什么是浏览器缓存?#

浏览器在首次请求网络资源后,将资源(如图片、JS、CSS等)存储在本地设备的机制

1.2 缓存的核心价值#

NOTE
  • 提升加载速度,减少等待时间
  • 减少重复请求,减小服务器压力
  • 节省网络带宽消耗,减少数据传输

二、缓存类型#

2.1 按存储位置划分#

缓存类型定义特点适用资源
Memory Cache(内存缓存)存储在浏览器内存中的临时缓存速度快生命周期短(关闭标签页 / 浏览器即消失);容量有限(仅存近期刚加载、可能复用的资源)体积较小的图片(如页面顶部临时图标);刚加载完的 JS/CSS 脚本(如页面渲染临时脚本)
Disk Cache(磁盘缓存)存储在本地磁盘中的持久化缓存,是强制缓存协商缓存的主要存储容器,浏览器依 HTTP 头(如Cache-Control)管理有效期速度中等(慢于内存、快于网络请求);生命周期长(关闭浏览器仍保留,需手动清除或过期);容量较大网站通用静态资源(如首页 logo、全局 CSS、长期不变的 JS 库如 jQuery);体积较大的资源(如轮播图图片、视频封面)
Service Worker Cache由「Service Worker」(浏览器后台独立线程,PWA 核心技术)管理的 “可编程缓存”,可自定义缓存逻辑完全可控(代码决定缓存资源、时长、删除时机,不依赖浏览器默认规则);持久化(需代码手动清除);支持离线(实现网页离线访问)PWA 核心资源(如离线页面 HTML、离线 JS/CSS、离线图标);需精准控制的资源(如电商商品详情页模板)
Push Cache(推送缓存)浏览器缓存 “最后一道防线”,HTTP/2 协议中 “服务器推送资源” 的临时缓存,使用场景极窄生命周期最短(仅存于当前会话,会话结束即消失);容量极小(仅缓存少量服务器推送资源);优先级最低(仅前三种缓存无资源时才检查)服务器通过 HTTP/2 推送的 “预加载资源”(如服务器预判用户访问页面,提前推送该页面的 CSS)

2.2 按策略划分#

缓存策略核心逻辑关键 HTTP 头核心特点适用场景
强制缓存(强缓存)有效期内直接用本地缓存,不发送服务器请求优先级:Cache-Control > Expires
Cache-Control:相对时间(如 max-age)
Expires:绝对时间
零网络请求,快;有效期内不更新(需哈希解决)长期不变静态资源(如第三方 JS、logo)
协商缓存(对比缓存强缓存过期后发验证请求(带标识),服务器判有效返 304 用缓存,无效返 200 + 新资源1. 时间戳组:If-Modified-Since / Last-Modified
2. 唯一标识组:If-None-Match / ETag
解决更新问题;需发轻量验证请求频繁更新需新鲜度资源(如新闻、商品页)
启发式缓存无缓存规则时,浏览器取 Date 与 Last-Modified 时差 10% 作为缓存有效期Date、Last-Modified(无则仅用 Date)兼容性兜底;不可控(浏览器有差异)无明确缓存规则的兜底场景

三、缓存核心机制:强缓存和协商缓存的双保险#

浏览器缓存机制流程图

四、如何正确设置缓存策略?#

IMPORTANT

最终目标:“高频资源快加载、更新资源能触达、源站压力降最低”

4.1 按资源类型制定策略#

资源类型核心特征推荐缓存策略具体配置示例(Cache-Control)原理说明
静态不变资源长期不更新、高频复用强缓存 + 超长有效期max-age=31536000(1 年)如第三方 JS 库(Vue/React)、logo、全局 CSS,用长强缓存最大化复用,更新靠版本控制(见第二部分)。
频繁更新静态资源周期性更新、需新鲜度协商缓存 + 短强缓存(降级)max-age=3600, stale-while-revalidate=86400如首页轮播图、活动 Banner:1 小时内用强缓存,过期后先返回缓存(保证速度),后台异步验证更新(保证新鲜度)。
HTML 页面承载动态内容、需即时更新协商缓存(禁用强缓存)no-cache(或max-age=0, must-revalidateHTML 是页面入口,若设强缓存,会导致整页无法更新;用no-cache强制每次发验证请求,确保获取最新结构。
动态内容(API 接口)实时性高、个性化禁用缓存 / 短时缓存(按需)no-store(完全不缓存)或max-age=60(1 分钟)如用户信息、商品实时价格:no-store确保每次获取最新数据;非实时接口(如分类列表)可设 1 分钟缓存减少请求。
临时资源(验证码、临时图标)单次使用、时效性极短禁用缓存no-store, no-cache避免缓存导致验证码重复、临时图标不刷新。

4.2 版本控制最佳实践#

IMPORTANT
  • 痛点:强缓存的最大痛点是 “有效期内资源更新无法触达浏览器
  • 原理版本控制的本质是 “内容变则标识变”,让浏览器识别 “新资源” 并重新请求
  • 关键原则
    • 版本标识仅用于静态资源(JS/CSS/ 图片),不用于 HTML(HTML 需协商缓存,确保能加载新资源路径)
    • 哈希值需与 “资源内容” 绑定,而非 “构建时间”,避免内容未变但哈希变化(如仅改注释导致缓存失效)

4.2.1 文件名哈希(推荐)#

  • 原理:将资源内容的哈希值(如 MD5、SHA256)嵌入文件名,资源内容变更时,哈希值自动变化,文件名随之改变(如logo.abc123.pnglogo.def456.png)。
  • 优势:精准关联 “内容 - 标识”,仅更新变化的资源,不影响其他缓存(增量更新)。
  • 实操示例:
    • 构建工具(Webpack/Vite)自动实现:配置output.filename: '[name].[contenthash].js',打包后生成index.8f2d7c.js
    • HTML 中引用新文件名:<img src="/static/logo.abc123.png">,资源更新后 HTML 引用logo.def456.png,浏览器自动请求新资源。

4.2.2 路径版本化#

  • 原理:在资源路径中加入版本号(如/v2/static/logo.png),资源整体更新时,修改路径中的版本号(如/v3/static/logo.png)。
  • 适用场景:资源批量更新(如网站大版本迭代),或无法修改文件名的场景(如老系统兼容)。
  • 注意:避免频繁全量更新(如每次改一点都换版本号),会导致所有缓存失效,增加服务器压力。

4.3 避免缓存陷阱#

CAUTION
陷阱类型现象描述根本原因解决方案
HTML 过度缓存页面更新后,用户仍看到旧页面(需强制刷新)给 HTML 设置了max-age=86400(长强缓存)HTML 仅用协商缓存:设置Cache-Control: no-cache,确保每次验证是否有新 HTML(新 HTML 会引用新资源)。
动态资源误设强缓存用户看到旧的 API 数据(如旧商品价格)给 API 接口(如/api/goods)设了max-age=3600动态接口按需缓存:实时数据设no-store;非实时数据设短max-age(如max-age=60),并配合服务器端 “缓存 - Control” 头。
跨环境缓存冲突开发环境资源缓存到生产环境,导致样式错乱开发 / 测试 / 生产环境共用同一域名,缓存键重复1. 环境加路径前缀:开发/dev/static/logo.png,生产/prod/static/logo.png
2. 开发环境强制禁用缓存(Cache-Control: no-store)。
缓存未命中(伪缓存)资源设了缓存,但浏览器仍频繁回源请求1. 资源 URL 带随机参数(如logo.png?t=123);2. 缓存头配置错误(如漏写Cache-Control1. 避免 URL 随机参数(用哈希版本替代);
2. 确保所有静态资源返回正确Cache-Control/Expires头;
3. 检查服务器是否拦截缓存头(如 Nginx 配置覆盖)。
ETag 重复导致协商失效资源内容变了,但 ETag 不变,服务器返 304ETag 基于 “文件大小 + 修改时间” 生成(而非内容哈希),内容变但大小 / 时间未变1. 服务器配置 ETag 为 “内容哈希”(如 Nginx 启用etag on;并确保基于内容计算);
2. 优先用Last-Modified(若资源修改时间精准)。

五、附录#

5.1 常见HTTP缓存头部速查表#

响应头#

头部名称核心作用关键值 / 指令典型场景
Cache-Control核心缓存控制(HTTP/1.1)- max-age=N(秒,强缓存期)- no-cache(需协商缓存)- no-store(不缓存)- public/private(缓存范围)带哈希 JS/CSS:public, max-age=31536000;HTML:no-cache
Expires强缓存过期时间(HTTP/1.0)绝对时间(如Wed, 20 Jul 2025 12:00:00 GMT兼容旧环境,优先级低于 Cache-Control
ETag协商缓存唯一标识资源哈希(如"abc123"需精准验证的资源(如 HTML、更新图片)
Last-Modified协商缓存最后修改时间绝对时间(如Tue, 10 Jun 2024 08:30:00 GMT静态资源,优先级低于 ETag

请求头#

头部名称核心作用关键值来源触发逻辑
If-None-Match验证 ETag 是否失效本地缓存的 ETag 值服务器对比:一致返 304,否则返 200 + 新资源
If-Modified-Since验证 Last-Modified 是否失效本地缓存的 Last-Modified 值服务器对比:资源未改返 304,否则返 200
Pragma兼容旧版缓存控制no-cache常用Cache-Control: no-cache,优先级最低

5.2 常见HTTP缓存相关状态码#

状态码核心含义缓存场景说明关键触发条件
200 OK资源请求成功1. 强缓存命中:响应头带from memory cache/from disk cache,不回源
2. 无缓存 / 缓存过期:回源获取新资源
1. 资源在max-age内,或未过期
2. 本地无缓存,或缓存失效且服务器返回新资源
304 Not Modified协商缓存命中,资源未更新不返回资源体,浏览器复用本地缓存,仅传输响应头请求携带If-None-Match/If-Modified-Since,服务器判断资源未修改
206 Partial Content部分资源请求成功复用本地缓存的部分资源(如大文件断点续传),仅回源缺失片段请求带Range头(指定资源片段),且本地缓存有对应片段
浏览器缓存
https://blog.oceanh.top/posts/frontend/浏览器缓存/
作者
Ocean Han
发布于
2025-09-19
许可协议
CC BY-NC-SA 4.0
最后修改时间
2025-09-20 10:09:15