应使用归类后的自定义设备标识(如x-device-type)替代user-agent做vary,通过nginx map模块统一枚举设备类型,仅对真实差异化资源启用vary,并确保cdn正确识别该头参与缓存键计算。

直接用 User-Agent 做 Vary 会严重破坏缓存命中率——UA 字符串千差万别,一个机型一个变体,CDN 缓存会被打散成海量碎片。真正可行的方案是:先归类、再标记、最后精准 Vary。
用 map 模块把机型归为有限枚举值
在 http 块中定义稳定设备标识变量,不依赖原始 UA 全字符串:
-
$device_type:统一归为mobile/tablet/desktop -
$phone_model:对高频机型做细粒度识别(可选),例如:
~*[Ii]phone\s?1[2-5] → iphone12
~*[Ss]amsung.*[Ss]2[3-5] → samsungs23 - 所有匹配规则必须覆盖全面,
default分支不可省略,避免变量为空
只对真实差异化内容响应添加 Vary
不是所有资源都需要按机型区分缓存。仅当后端实际返回了不同 HTML、JS 或图片时,才启用对应 Vary:
- 纯静态资源(如通用 CSS/JS)→ 不加 Vary
- 服务端渲染的首页 HTML → 若根据机型加载不同组件,则设
Vary: X-Device-Type - WebP 图片接口 → 若同时适配机型 + 格式,则设
Vary: X-Device-Type, Accept - 务必用自定义头(如
X-Device-Type)替代User-Agent,便于 CDN 理解且避免空格敏感问题
确保 Vary 头透传到 CDN 并参与缓存键计算
Nginx 输出的 Vary 必须被 CDN 正确识别,否则形同虚设:
- 在
location块中显式添加:add_header X-Device-Type $device_type;add_header Vary "X-Device-Type"; - 若使用代理缓存(
proxy_cache),同步更新proxy_cache_key:proxy_cache_key "$scheme$request_method$host$request_uri$device_type"; - 检查 CDN 控制台是否开启 Vary 支持(如 Cloudflare 默认支持,腾讯云需确认已恢复 Vary 特性)
验证是否生效的两个关键点
用 curl 对比不同机型请求的响应头与缓存状态:
- 发起两次请求,分别模拟 iPhone 14 和 Samsung S24 的 UA:
curl -I -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)..." https://yoursite.com/ - 确认响应头含
Vary: X-Device-Type且X-Device-Type值分别为mobile和mobile(或更细粒度值) - 观察
X-Cache或X-CF-Cache-Status是否出现 HIT/MISS 分离——相同机型第二次请求应 HIT,不同机型应 MISS(说明缓存隔离成功)











