浏览器为什么打开页面快

第二次访问同一个网站往往比第一次快很多,秘密是缓存。浏览器把响应过的资源按规则存起来,下次请求直接复用,省掉网络传输。HTTP 缓存分两类:强缓存,命中后完全不发请求直接用本地副本;协商缓存,带着标记问服务器,没变化就返回 304 继续用本地副本。

本文核心知识点
  • 强缓存Cache-Control 控制,命中不发请求。
  • 协商缓存ETag 与 Last-Modified 确认版本。
  • 指纹文件名带哈希,改版自然失效。
  • 分层HTML 不缓存、静态资源长缓存。
HTTP 缓存配图:蓝色渐变背景左侧浏览器窗口方块、中间多层存储柜方块、右侧服务器机柜方块,浏览器与存储柜之间双向箭头带对勾,扁平科技插画
浏览器与存储层之间的双向校验,正是 HTTP 缓存的意象。

强缓存:Cache-Control

Cache-Control 是强缓存的主控头,max-age 告诉浏览器缓存多少秒,public 表示允许中间缓存共享,immutable 表示内容不会变。静态资源配一年缓存很常见;HTML 这类会变的页面不要长缓存,否则用户看到的是旧页面。

Cache-Control: public, max-age=31536000, immutable

Expires 是老协议的绝对过期时间,现在基本被 Cache-Control 取代;两者同时存在时 Cache-Control 优先。

协商缓存:ETag 与 Last-Modified

资源不确定有没有变时用协商缓存:服务器返回时带 ETag(内容哈希)或 Last-Modified(最后修改时间),浏览器再请求时带上 If-None-Match 或 If-Modified-Since,服务器比较后没变就回 304,浏览器继续用缓存,只有响应头没有响应体,省流量。

响应头:ETag: "abc123"
再次请求:If-None-Match: "abc123"
命中返回:HTTP/1.1 304 Not Modified

ETag 比 Last-Modified 精确,内容变才会变;两者同时存在时 ETag 优先。协商缓存每次仍有一次网络往返,但比全量下载轻得多。

优先级与启发式缓存

缓存头的优先级从高到低大致是:Cache-Control 的 no-store 最强,禁止任何缓存;然后 no-cache 表示可缓存但要协商;接着 max-age 强缓存;再往后是 Expires 与 Last-Modified。没有显式缓存头的响应,浏览器会按启发式规则估计缓存时间,常见算法是取 Last-Modified 距今的十分之一,这会让旧资源缓存很久,所以关键响应要显式声明缓存策略。

// 敏感数据禁止缓存
Cache-Control: no-store

API 响应按业务定策略:个人数据 no-store,公开数据短缓存,静态资源长缓存,口径清晰不靠猜。

缓存策略设计

标准分层:HTML 不缓存或 no-cache,保证用户拿到最新页面;JS、CSS、图片等静态资源文件名带内容哈希,配一年强缓存,改版换文件名自然失效;字体、图标同理。这样页面更新靠 HTML 变化拉新,资源更新靠文件名变化,两者不冲突。

静态资源:/assets/app-a1b2c3.js
HTML 响应:Cache-Control: no-cache

CDN 层缓存静态资源会再快一步,但要保持与源站缓存口径一致,避免 CDN 缓存了不该缓存的东西。