讲讲 浏览器的缓存机制

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

一、整体缓存的流程

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

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

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

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

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

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

三、强缓存

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

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

强缓存靠两个响应头控制

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

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

  • 例子:

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

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

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

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

最常用:

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

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

其他常用值:

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

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

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

解决方案:文件名加哈希 / 版本号
复制代码
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. 第一次请求:服务器返回最后修改时间

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

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

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

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

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

工作流程:

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

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

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

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

五、完整的缓存工作流

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

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

1. HTML

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

2. CSS / JS / 图片

  • hash 指纹

  • 设置 长强缓存(一年)

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

3. 经常变的小文件

用协商缓存:

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

小结

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

相关推荐
Data_Journal1 小时前
Node.js网络爬取指南——简单易上手!
大数据·linux·服务器·前端·javascript
a1117761 小时前
可视化角色权限配置页面(html 开源)
前端·开源·html
Lee川1 小时前
个人中心与 AI 头像生成:从页面到 DALL-E 的完整实现
前端·架构
tedcloud1237 小时前
UI-TARS-desktop部署教程:构建AI桌面自动化系统
服务器·前端·人工智能·ui·自动化·github
Mahir0810 小时前
Redis 与 MySQL 数据同步:一致性保证的完整解决方案
数据库·redis·mysql·缓存·面试·数据一致性
UXbot10 小时前
AI原型设计工具如何支持团队协作与快速迭代
前端·交互·个人开发·ai编程·原型模式
ZC跨境爬虫11 小时前
跟着MDN学HTML_day_48:(Node接口)
前端·javascript·ui·html·音视频
多加点辣也没关系12 小时前
Redis 的安装(详细教程)
数据库·redis·缓存
刀法如飞12 小时前
Go 字符串查找的 20 种实现方式,用不同思路解决问题
算法·面试·程序员