配置 Cloudflare 缓存时,最容易混淆的是两件事:
- Cloudflare 边缘节点缓存多久。
- 用户浏览器本地缓存多久。
这两层都和缓存有关,但控制对象不同,风险也不同。
对静态博客来说,一个比较稳的思路是:Cloudflare 边缘缓存可以激进一点,浏览器缓存要保守一点。因为 Cloudflare 的缓存可以通过后台或 API 清掉,而用户浏览器本地缓存无法由站长直接清掉。
先分清三层位置
一次访问大致经过三层:
|
|
对应的缓存也有两类重点:
- Browser cache:浏览器存在用户本机的缓存。
- Edge cache:Cloudflare 存在边缘节点上的缓存。
源站 Nginx 返回的 Cache-Control 会影响浏览器,也可能影响 CDN。Cloudflare 的 Cache Rules 又可以单独设置 Edge TTL 和 Browser TTL。再加上 Response Header Transform Rules 还能改最终返回给浏览器的响应头,所以如果不分层,很容易以为“设置了缓存”就解决了一切。
Cache-Control 控制的是谁
Cloudflare 学习中心对 Cache-Control 的解释很直接:它是一个 HTTP 响应头,用来告诉浏览器和中间缓存如何处理资源。
常见指令有几个:
|
|
含义是:这个响应可以被缓存,浏览器最多缓存 300 秒。
|
|
含义是:只适合浏览器这类私有缓存保存,不应该被 CDN 这类共享缓存保存。
|
|
含义是:不要缓存,适合非常敏感的数据。
|
|
这个名字容易误导。它不是完全不缓存,而是使用缓存前必须先向服务器确认资源有没有更新。通常会配合 ETag 或 Last-Modified。
|
|
s-maxage 面向共享缓存,例如 CDN。它可以让 CDN 缓存更久,而浏览器仍按 max-age 或其他规则处理。
所以,Cache-Control 不是只给浏览器看的,也不是只给 CDN 看的。它是一组缓存规则,具体谁采用、谁覆盖,要看中间层怎么配置。
Cloudflare Edge TTL 和 Browser TTL 的区别
Cloudflare 里的两个 TTL 要分开看。
Edge TTL 决定 Cloudflare 边缘节点缓存多久。
例如:
|
|
意思是 Cloudflare 可以把页面、图片、CSS、JS 等内容存在边缘节点 1 天。访问者再次请求同一个 URL 时,如果缓存命中,Cloudflare 直接返回,不回源到 VPS。
Browser TTL 决定浏览器缓存多久。
例如:
|
|
意思是浏览器收到资源后,本地最多把它当作新鲜资源保存 5 分钟。5 分钟内用户再次访问,浏览器可能直接使用本地缓存;超过 5 分钟后,需要重新验证或重新请求。
两者最大的差别是:
- Edge cache 可以由站长
purge。 - Browser cache 在用户电脑里,站长没法直接清。
因此,HTML 页面不建议给浏览器很长 TTL。否则文章更新后,即使 Cloudflare 已经清缓存,用户浏览器仍可能继续用本地旧页面。
静态博客为什么适合缓存 HTML
动态网站通常不敢随便缓存 HTML,因为页面可能包含登录状态、用户资料、购物车、推荐内容、权限信息。
静态博客不一样。Hugo 生成的页面通常是纯静态文件:
- 首页。
- 文章页。
- 分类页。
- 标签页。
- 多语言页面。
- RSS。
- sitemap。
这些内容对所有访客基本一样,所以可以让 Cloudflare 缓存 HTML。这样做能减少回源请求,也能让海外访问更快。
但这里的关键是:
|
|
例如:
|
|
这表示 Cloudflare 可以缓存 1 天,但用户浏览器只缓存 5 分钟。
每次发布都 purge all 时,Edge TTL 可以更长
如果发布脚本每次都会调用 Cloudflare purge everything,那么 Edge TTL 可以设得更长。
逻辑是:
|
|
这种模式适合静态博客。因为站点内容不是实时变化,更新动作也集中在部署时。
Edge TTL 设 1 天和 1 个月都可以,区别主要是风险偏好:
1 day:如果某次 purge 失败,旧内容最多自然保留 1 天。1 month:缓存命中率更高,但 purge 失败时旧内容可能留更久。
普通个人博客先用 1 day 更稳。
为什么不建议浏览器也长缓存
浏览器缓存越长,重复访问越快,但更新越难控制。
比如 HTML 设置:
|
|
用户访问一次文章页后,浏览器可能把页面当作一年内都新鲜。你后面修改错字、更新链接、修正内容,Cloudflare purge 了也不一定影响这个用户的本地缓存。
静态资源可以长缓存,是因为它们通常带指纹文件名:
|
|
内容变了,文件名也变,旧缓存不会影响新页面引用的新文件。
但 HTML URL 通常不变:
|
|
所以 HTML 更适合短浏览器 TTL。
一种简单配置
如果希望简单,不想按文件类型细分,可以用一套统一策略:
|
|
Cloudflare Cache Rule 负责边缘缓存:
|
|
动作:
|
|
如果源站 Nginx 对 CSS/JS/图片设置了更长的 Cache-Control,而你又希望所有返回给浏览器的资源都统一为 5 分钟,可以在 Cloudflare 再加一条 Response Header Transform Rule:
|
|
这样就能做到:
- Edge 缓存由 Cloudflare Cache Rule 控制。
- Browser 缓存由 Cloudflare 响应头规则统一控制。
- Nginx 不需要为了浏览器 TTL 做统一改动。
什么时候需要分层缓存
如果追求更高性能,可以做分层:
|
|
这种配置更细,但维护成本也更高。个人博客一开始可以不用这么复杂。
当你确认所有静态资源都带 hash 文件名,再把 CSS/JS/图片的 Browser TTL 拉长,会更稳。
如何验证是否生效
可以用 curl -I 连续请求同一个 URL:
|
|
重点看两个头:
|
|
cf-cache-status: HIT 说明 Cloudflare 边缘缓存命中。
cache-control: public, max-age=300 说明浏览器端最多缓存 300 秒。
如果看到:
|
|
可能是第一次访问、刚 purge 过、规则还没生效,或者这个资源不符合缓存条件。再请求一次通常能看到 HIT。
如果 CSS/JS 仍显示:
|
|
说明浏览器缓存头仍由源站或某条更高优先级规则控制。要么接受静态资源长缓存,要么用 Cloudflare Response Header Transform Rule 覆盖。
小结
浏览器缓存和 Cloudflare 缓存不是一回事。
最实用的判断是:
- Cloudflare Edge 缓存可以激进,因为站长能 purge。
- 浏览器缓存要谨慎,因为站长不能清用户本地缓存。
- HTML 页面适合短 Browser TTL。
- 带 hash 的静态资源可以长 Browser TTL。
- 静态博客如果每次发布都 purge all,Edge TTL 设 1 天是一个稳妥起点。
对 Hugo 静态博客来说,先用:
|
|
就已经能获得大部分 CDN 加速收益,同时避免文章更新后长期显示旧页面。
参考链接
- Cloudflare:https://www.cloudflare.com/zh-cn/learning/cdn/glossary/what-is-cache-control/
- Cloudflare Cache Rules:https://developers.cloudflare.com/cache/how-to/cache-rules/
- Cloudflare Response Header Transform Rules:https://developers.cloudflare.com/rules/transform/response-header-modification/