浏览器缓存最强攻略:强缓存、协商缓存、CDN、更新策略,一篇搞定
网站加载慢重复请求浪费带宽用户总是看到旧版本这些问题背后都指向同一个关键词缓存。今天我们从HTTP头开始彻底搞懂强缓存、协商缓存、CDN缓存、前端静态资源版本管理以及最常见的缓存坑和解决方案。一、缓存是什么为什么重要缓存是HTTP协议中用于复用之前获取的资源的机制。合理使用缓存可以减少网络请求页面加载更快降低服务器压力节省用户流量但缓存用不好会导致用户看到过期内容或者每次都重新下载失去缓存意义。二、强缓存服务器告诉浏览器“别问了直接用旧的”强缓存由服务器返回的响应头中的Cache-ControlHTTP/1.1或ExpiresHTTP/1.0已过时控制。2.1 Cache-Control 常用指令指令含义max-age3600资源在3600秒内是“新鲜的”直接使用缓存不请求服务器no-cache跳过强缓存但可以用协商缓存见下文no-store完全不缓存每次都重新下载public可以被任何中间节点CDN、代理缓存private只能被浏览器缓存不能给中间节点如用户个人信息immutable资源永不变化通常配合带hash的文件名使用浏览器不必再验证2.2 强缓存流程浏览器请求资源 → 服务器返回资源 Cache-Control: max-age3600 → 浏览器缓存该资源3600秒内再次请求直接读缓存200 from disk cache → 3600秒后重新请求服务器2.3 如何绕过强缓存刷新页面F5 / CmdR浏览器会带上Cache-Control: max-age0告诉服务器不要用缓存走协商缓存。硬刷新CtrlF5 / CmdShiftR浏览器带上Cache-Control: no-cache强制重新下载。三、协商缓存浏览器问服务器“资源变了吗”当强缓存过期或者请求头带有Cache-Control: no-cache时浏览器会发起协商缓存请求询问服务器资源是否有更新。3.1 Last-Modified / If-Modified-Since服务器返回Last-Modified资源最后修改时间浏览器下次请求带上If-Modified-Since。服务器比对时间若未修改则返回304 Not Modified浏览器使用缓存若修改则返回200和新资源。缺点时间精度为秒如果文件在1秒内多次修改可能无法检测到。如果文件内容没变但时间变了如CI重新生成也会导致重新下载。3.2 ETag / If-None-Match推荐ETag是服务器根据文件内容生成的唯一标识哈希值更精确。浏览器下次请求带上If-None-Match: 某hash。若未变则返回304否则返回200和新资源。优先级ETag 高于 Last-Modified。3.3 协商缓存流程浏览器: 我有个资源ETag是abc你变了没 服务器: 没变304你继续用旧的 浏览器: 用缓存四、强缓存 vs 协商缓存对比特性强缓存协商缓存发起请求不发直接用缓存发但服务端不返回体状态码200 (from disk/memory cache)304控制头Cache-Control / ExpiresLast-Modified / ETag适用场景不常变的静态资源JS/CSS/图片可能变化的HTML、API响应五、最佳实践如何配置5.1 静态资源JS/CSS/图片强缓存 文件名hashlocation ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 1y; add_header Cache-Control public, immutable; }注意文件名必须带hash如main.a3f2b1c.js内容变化时hash变化浏览器才会重新下载。这是目前最主流的前端静态资源缓存策略。5.2 HTML文件协商缓存或 no-cachelocation ~ \.html$ { add_header Cache-Control no-cache; }因为HTML需要随时更新入口文件不能强缓存。5.3 API响应按需动态数据Cache-Control: no-cache相对固定的数据如配置Cache-Control: max-age60短时缓存六、前端更新痛点与解决方案问题用户看到旧版本常见于部署新版本后用户浏览器缓存的旧CSS/JS未更新导致页面错乱。入口HTML被强缓存用户没拿到新版本入口自然不会请求新资源。解决方案HTML文件用协商缓存或短时缓存如max-age60。静态资源用文件名hash 强缓存。通过构建工具Webpack/Vite自动生成带hash的文件名。部署时先上静态资源后上HTML。确保HTML引用的是最新的资源hash。可选项在HTML中插入版本号或 query string不推荐因为可能被代理忽略。七、CDN缓存CDN是“反向代理缓存”缓存静态资源在全球边缘节点。配置时需注意通过Cache-Control: public允许CDN缓存。设置合适的max-age太短会增加回源请求太长会导致更新不及时。刷新CDN缓存通常需要手动调用API或版本化URL。八、调试缓存Chrome DevToolsNetwork面板Size 列显示(memory cache)、(disk cache)或状态码304。Disable cache复选框临时禁止缓存仅限DevTools开启时。Application→Cache Storage查看Service Worker缓存。Clear site data清除当前网站的缓存。常用命令硬刷新CmdShiftR(Mac) /CtrlF5(Windows)清除缓存并硬刷新打开DevTools后右键刷新按钮选择“Empty Cache and Hard Reload”九、常见坑点坑原因解决上线后用户还是旧版本HTML被强缓存HTML用no-cache或短时缓存CSS改了页面样式还是旧的CSS文件名没变浏览器强缓存文件名加hash图片更新了还是旧图CDN缓存未刷新版本化URL或主动刷新CDN304请求多还是慢强缓存没开每次都协商给静态资源加max-age十、总结场景推荐配置静态资源带hashCache-Control: max-age31536000, immutableHTML入口Cache-Control: no-cacheAPI不变数据Cache-Control: max-age60API动态Cache-Control: no-cache用户头像等私有资源Cache-Control: private, max-age3600缓存策略没有“标准答案”需要根据业务需求权衡实时性和性能。但记住带hash的静态资源放心强缓存入口文件绝不强缓存。