外观
浏览器缓存怎么回答?
强缓存命中时浏览器不发请求。协商缓存每次都要问服务器,资源没变就返回 304,沿用本地副本。线上页面用「HTML 短缓存或协商,带内容哈希的静态资源长缓存」。
原理
强缓存看 Cache-Control: max-age=...(HTTP/1.1)或过期的 Expires。年龄还没到,直接用磁盘或内存里的副本,状态仍是 200,开发者工具里会标 from disk cache 或 from memory cache。
协商缓存把校验令牌发给服务器:
ETag配请求头If-None-MatchLast-Modified配If-Modified-Since
没变化就 304,没有响应体。变了就 200 并带上新内容。两者都在时以 ETag 为准。ETag 能分辨同一秒内的变化,也能避免服务器时间不准;Last-Modified 更便宜。
几个容易混的指令:
no-cache:可以存,但使用前必须向服务器验证。它不是「不缓存」。no-store:不写入缓存。private:只允许浏览器缓存,共享缓存(例如中间代理)不行。immutable:在过期前不要为了刷新而重新验证,适合带哈希的文件名。
HTML 如果也缓存一年,用户会一直拿到旧的入口,里面的旧哈希文件名也就不会更新。所以入口文档要能较快失效,静态资源文件名带上内容哈希之后可以缓存很久。
追问
刷新和强刷有什么差别?
普通刷新仍可能走协商缓存。强制刷新会避开缓存重新要一份。地址栏回车更可能直接吃强缓存。面试时说明自己指的是哪一种操作。
协商缓存为什么还要设计?
强缓存期间服务器没法让客户端立刻更新。协商缓存用一次很轻的往返换「变了才下载」。
易错点
no-cache不等于no-store。- 304 是缓存生效,不是出错。
- 只给 JS/CSS 加长缓存、却不改文件名,用户会一直跑旧脚本。