浏览器缓存机制
Contents
缓存流程概述
浏览器缓存主要分为 强缓存 和 协商缓存,目的是减少网络请求、降低服务器压力、提升页面加载速度。
浏览器首次请求资源时:
- 服务器返回资源 + 响应头(包含缓存控制字段)。
后续请求时:
- 浏览器先检查 强缓存 是否命中(优先级最高)。
- 命中:直接从本地(内存或磁盘)读取资源,状态码 200 (from disk/memory cache),不发请求。
- 未命中:进入协商缓存。
- 协商缓存:
- 浏览器 发请求,携带验证字段。
- 服务器判断资源是否变更:
- 未变更:返回 304 Not Modified(不返回资源体),浏览器从缓存读取。
- 变更:返回 200 + 新资源。
强缓存
通过响应头控制资源过期时间(不向服务器发请求)。
命中强缓存 Network 面板显示 200 (from disk cache) 或 200 (from memory cache)。
Cache-Control
使用更灵活的相对时间,多个指令可组合(如Cache-Control: max-age=3600, public)。
常见指令:
max-age=<seconds>:缓存有效时长(相对请求时间)。no-cache:跳过强缓存,但允许协商缓存(每次验证)。no-store:完全禁用缓存(包括协商),每次请求新鲜资源。public:允许共享缓存(CDN、代理)。private:仅浏览器私有缓存。immutable:资源永不变化(常用于带hash的文件)。
协商缓存
强缓存过期后会触发协商缓存,服务器根据资源标识判断是否变更(向服务器发请求验证)。
| 字段对 | 所属协议 | 说明 | 优先级/注意点 |
|---|---|---|---|
| Last-Modified / If-Modified-Since | HTTP/1.0 | 基于最后修改时间(秒级精度)。 | 精度低(秒内多次修改无效);分布式服务器时间可能不一致。 |
| ETag / If-None-Match | HTTP/1.1 | 基于资源内容hash(唯一标识)。可强/弱校验(W/开头为弱)。 | 优先于Last-Modified。更精确(内容不变,ETag不变)。推荐使用。 |
流程:
- 首次响应:服务器返回 Last-Modified 或 ETag。
- 后续请求:浏览器携带 If-Modified-Since 或 If-None-Match。
- 服务器判断资源是否变更:
- 未变更:返回 304 Not Modified(不返回资源体),浏览器从缓存读取。
- 变更:返回 200 + 新资源。
ETag优势:内容相同但修改时间变了,仍可命中缓存。
不同刷新方式的影响
| 操作 | 强缓存 | 协商缓存 | 说明 |
|---|---|---|---|
| 地址栏回车/链接跳转 | 检查 | 检查 | 正常触发缓存机制。 |
| F5 / 刷新按钮 | 忽略 | 检查 | Cache-Control: max-age=0,等价no-cache。 |
| Ctrl+F5 / 强制刷新 | 忽略 | 忽略 | 添加no-cache/no-store,直接请求新资源。 |
前端性能优化
- 静态资源(JS/CSS/图片,带hash文件名,如
app.a1b2c3.js):强缓存长期有效(max-age=31536000, immutable)。 - 入口HTML:协商缓存(
no-cache),确保更新时拉取最新(引用新hash资源)。 - 动态资源:
no-store或no-cache。 - Nginx/服务器配置示例:
location ~ \.(js|css|png|jpg)$ { add_header Cache-Control "max-age=31536000, immutable"; } location = /index.html { add_header Cache-Control "no-cache"; }