前端 CDN 缓存策略调优:静态资源、HTML 与 API 分层设计

发布时间:2026/7/10 22:51:46
前端 CDN 缓存策略调优:静态资源、HTML 与 API 分层设计 前端 CDN 缓存策略调优静态资源、HTML 与 API 分层设计一、改了静态资源用户看到的还是旧页面前端缓存配置三大常见错误HTML 和 JS 用了同一种缓存策略静态资源没做 hash导致强制缓存后更新困难API 响应被 CDN 错误缓存这三个错误的根源都是没按文件类型做分层缓存。HTML 需要短缓存或不缓存确保用户拿到最新页面静态资源JS/CSS可以长缓存配合文件 hash 做版本化API 的缓存策略取决于数据特性。flowchart TD A[浏览器请求] -- B{资源类型} B --|HTML 页面| C[Cache-Control: no-cachebr/或 max-age0, must-revalidate] B --|静态资源 JS/CSS| D[Cache-Control: max-age31536000, immutable] B --|API 响应| E{数据类型} C -- F[CDN 缓存: 不做或短缓存] D -- G{文件名含 hash?} G --|是| H[CDN 缓存: 永久] G --|否| I[CDN 缓存: 短缓存 版本参数] E --|实时数据| J[Cache-Control: no-store] E --|半实时| K[Cache-Control: max-age60, stale-while-revalidate300] E --|静态数据| L[Cache-Control: max-age3600]二、分层的核心原则第一层HTML 入口文件Cache-Control: public, max-age0, must-revalidate CDN: 不做缓存这是最关键的一层。HTML 引用了所有 JS/CSS如果 HTML 被缓存了用户拿到的是旧版 HTML它引用的是旧版 JS/CSS——整条缓存链全废了。max-age0, must-revalidate不是不缓存是每次请求都要验证conditional request。CDN 回源验证如果 304 Not ModifiedCDN 返回缓存的副本。这个开销比完全重新下载小得多。第二层静态资源JS/CSS/Font/ImageCache-Control: public, max-age31536000, immutable CDN: 长缓存配合文件 hash文件名带 content hash如main.a3f2b1c.js资源永久不可变。immutable告诉浏览器即使强制刷新也不要重新验证——因为内容永远不会变。这是 Webpack/Vite 的默认策略。第三层API 响应API 的缓存最复杂需要根据数据特性细分实时数据Cache-Control: no-store不缓存每次请求源站半实时数据Cache-Control: max-age60, stale-while-revalidate300缓存 60 秒过期后允许返回过期数据 300 秒的同时后台异步刷新准静态数据Cache-Control: max-age3600, stale-while-revalidate86400三、Nginx CDN 分层配置# nginx.conf —— 按文件路径分层缓存 # 第一层HTML 入口文件 # 指定 HTML 类型的请求不做 CDN 长缓存 location / { # 对于 SPA 的入口 HTML if ($request_uri ~* \.html$) { add_header Cache-Control public, max-age0, must-revalidate always; # X-Cache-Bypass 告诉 CDN 每次都回源验证 add_header X-Cache-Bypass 1 always; } # try_files 优先找精确文件找不到 fallback 到 index.htmlSPA 路由 try_files $uri $uri/ /index.html; } # 第二层静态资源带 hash 的文件名 location /assets/ { # 静态资源目录所有文件带 hash expires 1y; add_header Cache-Control public, max-age31536000, immutable always; # 关键安全头禁止 MIME 嗅探 add_header X-Content-Type-Options nosniff always; # 为不同类型设置正确的 Content-Type types { application/javascript js mjs; text/css css; image/svgxml svg; font/woff2 woff2; } # gzip 预压缩——CDN 可以直接返回预压缩文件 gzip_static on; gzip_vary on; } # 第三层API 代理 location /api/ { proxy_pass http://backend-service; # 基础代理设置 proxy_http_version 1.1; proxy_set_header Connection ; # 根据 URL 前缀设置不同的缓存策略 # 分类依据数据的变化频率 # 实时数据不缓存 location /api/realtime/ { proxy_pass http://backend-service; add_header Cache-Control no-store always; } # 半实时数据短缓存 stale-while-revalidate location /api/dashboard/ { proxy_pass http://backend-service; add_header Cache-Control public, max-age60, stale-while-revalidate300 always; } # 准静态数据长缓存 location /api/config/ { proxy_pass http://backend-service; add_header Cache-Control public, max-age3600, stale-while-revalidate86400 always; } }四、缓存更新与失效策略静态资源的缓存更新文件 hash 是核心武器。部署流程构建时生成带 hash 的文件名main.a3f2b1c.jsHTML 更新引用新的 hash 文件名部署到 CDN——新文件有新的 URL旧文件保留不影响旧 HTML 的用户用户下次请求 HTML 时获取新引用这就是为什么 HTML 不能用长缓存——它是切换开关。CDN 主动刷新# 批量刷新目录下的所有文件 curl -X POST https://cdn-provider/api/purge \ -H Authorization: Bearer $CDN_TOKEN \ -d {paths: [/assets/*]}注意干完活要等 CDN 节点生效——全球 CDN 刷新通常需要 1-5 分钟。不建议的做法给静态资源加版本查询参数main.js?v1.2.3很多 CDN 默认忽略 query string缓存不生效HTML 也做长缓存一旦缓存用户永远看不到新版本没有 stale-while-revalidate 的长缓存缓存过期瞬间所有请求打回源站五、总结前端缓存的分层设计核心就一句话HTML 是开关静态资源是货物API 是水龙头。开关要灵敏短缓存/不缓存货物可以囤长缓存 hash水龙头按需开数据特性决定缓存策略。三层各自独立配置后缓存命中率可以从 40% 提升到 90%源站压力下降 2/3。