# 缓存实践
原文:Caching best practices & max-age gotchas (opens new window)
缓存大多分为两种模式:
- 不可变内容 + 很长的
max-age
值 - 可变内容,总是需要经过服务器重新验证
# 不可变内容 + 很长的 max-age
值
Cache-Control: max-age=31536000
1
此种模式:
- 一个固定的 URL 指向的内容永远不会变,要变就是直接变 URL 。
- 浏览器或CDN将这个资源缓存一年不会有任何问题
- 缓存内容的时间小于
max-age
时(也就是缓存未失效),可以直接使用,不需要询问服务器来验证它。
适用情况:
<script src="/script-f93bca2c.js"></script>
<link rel="stylesheet" href="/styles-a837cb1e.css" />
<img src="/cats-0e9a2ef4.jpg" alt="…" />
1
2
3
2
3
每一个资源文件经过打包后,会根据内容生成一个唯一的 hash 值,如果文件内容有变化,则这个 hash 值会变化,也就是访问的 URL 就会变化,一个固定的 URL 指向的内容是肯定不会有变化的。
然而,这种模式不适用于文章和博客文章。它们的 URL 不能变,也就是不能使用文件 hash 值作为 URL,但内容是需要改变更新的。比如基本拼写和语法错误,修改之后,必须保持原来的 URL。
# 可变内容,总是需要经过服务器重新验证
Cache-Control: no-cache
1
此种模式:
- 一个固定 URL 的内容可能会改变
- 所有缓存文件在使用时,都需要经过服务器校验是否有更新
注意: no-cache
并不意味着“不缓存”,它意味着在使用缓存资源之前必须由服务器来检查 (revalidate)。no-store
才是告诉浏览器不要缓存它。此外,must-revalidate
并不意味着“必须重新验证”,它的意思是,如果本地资源缓存时间小于提供的 max-age
,则可以使用它,否则必须重新验证。
在这种模式中,可以在响应头种,添加 ETag
(你选择的版本ID) 或 Last-Modified
。下次客户端获取资源时,会在请求头中,通过 If-None-Match
带上上一次获取的 ETag
,或通过 If-Modified-Since
带上上一次获取的 Last-Modified
来询问服务器。如果服务器校验没有发现更新,则会告诉客户端:“你的资源已经是最新的了,直接使用就行了”。
如果服务端无法发送 ETag
或 Last-Modified
,那么服务端总是会返回完整的文件资源。
这种模式,总是涉及到网络连接,所以它不如前一种模式好,因为前一种模式在缓存未失效时,可以完全不使用网络。