index.html缓存必须设no-cache或max-age=0,must-revalidate,禁用public/max-age长缓存;动态页用private,max-age=0,must-revalidate;敏感页用no-store;静态页可用public,max-age=3600但需JS/CSS带内容哈希。

Cache-Control 必须按页面动态性配,不是加了就快,配错反而卡用户在旧版 HTML 里。
index.html 的 Cache-Control 怎么设才不翻车
绝大多数线上故障都源于给 index.html 错误地配置了 public, max-age=3600:用户加载的仍是旧 HTML,但新 JS 已上线,导致按钮消失、路由 404、CSS 类名失效。
- 静态页(文档、博客文章)可用
public, max-age=3600,但前提是所有 JS/CSS 路径含内容哈希(如main.a1b2c3.js) - 带登录态或用户数据的页面(仪表盘、订单页),必须用
private, max-age=0, must-revalidate—— 允许缓存,但每次都要向服务器验证是否更新 - 敏感页(登录、支付确认)必须用
no-store,禁用一切缓存,连磁盘都不许写 -
meta http-equiv="Cache-Control"在 Chrome/Firefox/Edge 中完全无效,只在极老 Safari 上有降级行为,别写
为什么 JS 放 <head> 里不加 defer 就等于白优化
HTML 解析是流式的,<script> 阻塞解析时长直接决定白屏时间。缓存再快,也救不了被卡住的 DOM 构建。
- 绝对不要把业务脚本(如表单校验、组件初始化)放在
<head>且不加defer—— 这会暂停整个 HTML 解析 - 优先用
defer:下载不阻塞,执行时机确定(DOM 构建完成后) - 无依赖埋点脚本(如 GA、Sentry)可用
async:下载不阻塞,但执行时机不可控,不能依赖 DOM - 内联 JS 控制在 1KB 以内;超量必须外链,否则 parser blocking 在低端设备上明显拉长
HTML 缓存生效的前提不是设头,而是构建和部署闭环
光配 Cache-Control: public, max-age=31536000 没用。如果 JS 文件名没变但内容变了,浏览器照旧加载旧逻辑。
- JS/CSS 必须启用 content hash 输出(Webpack 的
contenthash,Vite 默认行为) - 服务端必须启用 Gzip 或 Brotli 压缩:
gzip on或brotli on,HTML 体积通常缩小 50%~70% - CDN 或 Nginx 的
location块要单独配 HTML 缓存策略,不能和静态资源共用同一规则 -
html-webpack-plugin的cache: true只加速本地编译,不影响浏览器缓存行为
页面缓存 vs 片段缓存:别拿整页缓存硬套个性化页面
电商详情页右上角显示“购物车(3)”,三个用户看到的数字不同 —— 这种页面没法整页缓存。强行缓存会导致串号、状态错乱。
立即学习“前端免费学习笔记(深入)”;
- 页面缓存适合内容固定、访问量大的场景(文章页、公告页、首页静态区块)
- 片段缓存才是解法:把“正文”“推荐栏”等静态块单独缓存,把“用户头像”“实时价格”等动态块保留每次渲染,最后拼接
- 服务端做片段缓存时,缓存键必须包含用户身份标识(如
user_id或session_id),否则动态内容会污染缓存 - 浏览器端无法安全做片段缓存,因为无法隔离用户上下文;这类逻辑必须由服务端或 Service Worker 控制
index.html 的 Cache-Control 和 JS 加载方式,这两个点一旦出错,其他优化全归零。



















