讲讲 浏览器的缓存机制

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

一、整体缓存的流程

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

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

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

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

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

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

三、强缓存

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

表现:速度极快,网络面板显示 disk cachememory 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 牵引

相关推荐
AI砖家1 小时前
DeepSeek TUI 保姆级安装配置全指南 -Windows||macOS双平台全覆盖
服务器·前端·人工智能·windows·macos·ai编程·策略模式
Apache0121 小时前
chrome调试打开,让AI来操作浏览器
前端·chrome
lbaihao1 小时前
LLVM Cpu0 调用规则解析
开发语言·前端·python·llvm
木子墨5161 小时前
系统设计面试 | 实现一个限流器:滑动窗口 → 令牌桶 → 漏桶
java·开发语言·数据结构·数据库·面试·职场和发展
hexu_blog2 小时前
前端vue 后端springboot如何实现图片去水印
前端·javascript·vue.js
whuhewei2 小时前
React搜索框组件
前端·javascript·react.js
姓王者2 小时前
Cloudflare Pages自定义依赖安装实践 | 姓王者的博客
前端
stringwu2 小时前
Flutter 开发的 AI 三件套:壮汉、法师、实习生
前端
代码搬运媛2 小时前
BFF 架构浅析:再也不用求后端改接口了
前端