能安全缓存的模板片段必须完全静态、无用户上下文、不依赖请求变量,如纯产品卡片、通用页脚、帮助文档段落;含{{.CurrentUser.Name}}或{{.CSRFToken}}的片段禁用缓存;缓存键须包含locale、设备类型、AB分组、权限等级等维度;需动态注入ID前缀避免hydration冲突,并关闭CDN的HTML自动优化功能。

哪些模板片段能安全缓存?
能缓存的只有完全静态、不带任何用户上下文或请求变量的 HTML 片段。比如纯产品卡片(只含 product.Name、product.Price)、通用页脚(不含登录按钮)、帮助文档段落(Markdown 渲染后无 session 数据)。一旦模板里出现 {{.CurrentUser.Name}} 或 {{.CSRFToken}},整个片段就必须禁用缓存——否则 A 用户的昵称可能被 B 用户看到。
缓存 key 必须包含哪些维度?
不能只按文件名缓存 "header.templ",而要拼出带签名的 key,覆盖所有影响输出的变量:
- 当前
locale(如zh-CN) - 设备类型(
desktop/mobile,影响<picture>候选集) - AB 实验分组(
exp=checkout-v2) - 权限等级(
role=guest/role=admin)
错误写法:cache.Get("header");正确写法:cache.Get("header:zh-CN:mobile:guest")。Go 的 templ 引擎不自动拼 key,必须在调用层手动处理。
为什么不能缓存含内联 <script> 的片段?
SSR 渲染后的内联脚本在客户端会重复执行,且缓存中的 <script> 标签无法随状态更新。更危险的是 hydration 冲突:多个服务返回的碎片都含 id="loading",合并后只剩一个生效,导致事件绑定错位、焦点丢失。
立即学习“前端免费学习笔记(深入)”;
解决方案不是删 ID,而是动态注入前缀:id="{{.FragmentID}}-loading",客户端 hydrate 前批量重写 ID。绝对不要在模板里写固定 id="sidebar"。
CDN 缓存 HTML 碎片时要注意什么?
Cloudflare、阿里云 CDN 默认开启“HTML 自动优化”,会补全 <tbody>、移除注释、压缩空格——这直接破坏 templ 渲染的精确结构,尤其当碎片含条件注释或 JS 字符串插值时。
必须在 CDN 后台关闭 HTML 自动修正功能。同时,index.html 本身不该长期缓存,应返回 Cache-Control: no-cache 或 max-age=0, must-revalidate;带哈希的静态资源(如 app.8f3e2d.css)才适合设 public, immutable, max-age=31536000。
缓存粒度宁小勿大,一个 <nav> 比整个 <body> 安全得多——出问题时影响范围可控,也更容易定位 stale data 来源。



















