讲讲 浏览器的缓存机制

浏览器缓存的核心目的就是:让浏览器少发请求、少下载资源,也就等同于让页面更快、服务器压力更小。

一、整体缓存的流程

浏览器请求一个静态资源,如:CSS、JS、图片时,顺序判断:

  1. 先查强缓存
    • 有效->直接使用本地缓存,不发请求(最快)
    • 无效->进入下一步
  2. 再查协商缓存
    • 发请求问服务器:资源变了吗?
    • 没变->返回304,直接用本地缓存
    • 变了->返回200+新资源
  3. 如果都不生效->全新请求 200+新资源

二、重点:为什么HTML 不缓存?

HTML 永远不做缓存,每次请求都必须重新请求。 原因是:

  • HTML 是"入口文件",里面引入了CSS、JS、图片
  • 如果HTML 被缓存了,你更新了页面,用户永远也看不懂你更新的新版页面
  • 浏览器每次必须拿到最新的HTML,才知道里面的资源要不要更新

这是前端工程化的基础规则。

三、强缓存

定义:浏览器直接从本地拿资源,完全不发请求到服务器。

表现:速度极快,网络面板显示 disk cache 或 memory cache。

强缓存靠两个响应头控制

第一种:Expires(HTTP 1.0,老式、不推荐)

  • 格式:绝对时间(格林威治时间)

  • 例子:

    yaml 复制代码
    Expires: Wed, 31 Dec 2026 23:59:59 GMT
  • 意思:在这个时间点之前,都用缓存

致命缺点:依赖客户端本地时间。如果用户电脑乱了、时区错误,缓存直接永远失效或者永远不会过期。

第二种:Cache-Control(HTTP 1.1,现代标准、必用)

用相对时间,不依赖客户端时间,最稳定。

最常用:

ini 复制代码
Cache-Control: max-age=86400

意思:资源缓存 86400 秒 = 1 天

其他常用值:

  • no-cache:跳过强缓存,直接走协商缓存
  • no-store:完全不缓存(敏感数据用)
  • public:所有地方都可缓存
  • private:只有浏览器能缓存

重点问题:资源提前更新了,缓存没到期怎么办?

比如:你改了 CSS,但用户浏览器缓存还有 10 天才过期。

解决方案:文件名加哈希 / 版本号
diff 复制代码
index.css?v=123
或者
index.abc123.css
原理
  1. HTML 每次都重新请求
  2. 新版 HTML 里引用的是新地址的 CSS
  3. 浏览器发现 URL 不一样 → 当作全新资源
  4. 直接放弃旧缓存,下载新文件

这就是前端打包工具(Webpack/Vite)自动给静态资源文件加哈希的原因。

四、协商缓存

定义:强缓存过期后,浏览器必须发请求询问服务器缓存资源是否还能用。

协商缓存两套机制

第一种:Last-Modified / If-Modified-Since(HTTP 1.0)

工作流程:

  1. 第一次请求:服务器返回最后修改时间

    yaml 复制代码
    Last-Modified: Tue, 01 Jan 2025 12:00:00 GMT
  2. 强缓存过期后,浏览器发请求带上上次服务器返回的最后修改时间:

    yaml 复制代码
    If-Modified-Since: Tue, 01 Jan 2025 12:00:00 GMT
  3. 服务器对比时间:

    • 一致 → 304 不是拿缓存,是允许使用缓存 304响应体几乎没有内容
    • 不一致 → 200 + 新资源
缺点
  • 只看时间,不看内容
  • 秒级修改可能识别不到
  • 服务器时间不同步会出问题

ETag / If-None-Match(HTTP 1.1,更精准)

基于文件内容生成唯一指纹(hash) ,比时间更可靠。

工作流程:

  1. 第一次请求:服务器返回

    vbnet 复制代码
    ETag: "abc123xyz"
  2. 再次请求(强缓存过期):

    sql 复制代码
    If-None-Match: "abc123xyz"
  3. 服务器对比 hash:

    • 一样 → 304
    • 不一样 → 200 + 新资源
优点
  • 优先级高于 Last-Modified
  • 内容变才会变,时间乱改不影响
  • 精准度 100%
缺点
  • 服务器要计算 hash,轻微增加性能消耗

五、完整的缓存工作流

sql 复制代码
浏览器请求资源
  ↓
检查强缓存(Cache-Control / Expires)
  ↓
有效?→ 直接用本地缓存(不发请求)
  ↓
无效?→ 发请求走协商缓存
  ↓
服务器对比 ETag / Last-Modified
  ↓
未修改 → 304,用本地缓存
  ↓
已修改 → 200,返回新资源

六、我们实际开发中怎么配置?

1. HTML

不设置强缓存,每次都重新请求

2. CSS / JS / 图片

  • 加 hash 指纹

  • 设置 长强缓存(一年)

    ini 复制代码
    Cache-Control: max-age=31536000

3. 经常变的小文件

用协商缓存:

yaml 复制代码
Cache-Control: no-cache
// noe-cache 跳过强缓存,直接走协商缓存

小结

强缓存不发请求最快,协商缓存发请求校验;HTML 永远不缓存,静态资源加指纹永不过期,更新全靠 HTML 牵引。

相关推荐
怕浪猫6 小时前
Claude Code vs Codex:Computer Use 实现原理深度拆解
算法·面试·github
itmigrate6 小时前
前端项目里,Object.is 并不是 === 的平替
前端
小大宇7 小时前
Vue知识点6-computed计算属性
前端·javascript·vue.js
程序员海军8 小时前
尤雨溪 : Vue 4 已经在规划中了!
前端·javascript·vue.js
2601_949970698 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
风骏时光牛马9 小时前
后端服务接口开发与性能优化
前端
kyriewen10 小时前
我让 4 个 AI 互相 review 代码,最温柔的那个下手最狠
前端·程序员·ai编程
考研保研资料分享10 小时前
无论文竞赛保研中科院植物所:三场考核、科研追问与准备复盘
面试
计算机魔术师10 小时前
493家公司白砸AI钱?Apollo这组数据戳破了幻觉
前端
救救孩子把10 小时前
AI面试八股文-23_23-Agent可观测性与生产监控面试题
人工智能·面试·职场和发展·agent·langsmith·langfuase