CDN缓存效果取决于浏览器发出的URL是否静态且规范:srcset/sizes/type需正确,避免动态参数;Content-Type须严格匹配type属性;sizes应真实反映CSS布局宽度;路径需静态清晰;语法错误会导致全部<source>失效。

CDN 本身不理解 picture,它只按 URL 缓存和分发;真正影响 CDN 效果的是你写的 srcset、sizes 和 type 是否让浏览器发出「可被 CDN 高效缓存」的请求。
CDN 缓存命中率低,往往是因为浏览器发出了太多唯一 URL
常见错误是把 srcset 写成带动态参数的路径,比如:photo.jpg?ts=123456 或 photo.jpg?dpr=2。这类 URL 每次都不同,CDN 当作新资源处理,缓存失效。
- 所有图片 URL 必须是静态路径,不含时间戳、DPR 参数、用户 ID 等变量
- 设备像素比(DPR)由浏览器自动匹配
srcset中的1x/2x,不需要你在 URL 里拼接 - 如果后端做了基于 User-Agent 的格式协商(如 AVIF/WebP/JPEG),确保 CDN 配置了 Vary: Accept 头,否则可能缓存错格式
WebP/AVIF 回退链在 CDN 上必须严格对齐 MIME 类型
CDN 通常不会校验响应头,但浏览器会。如果你用 type="image/avif",而 CDN 回源后返回的 Content-Type 是 image/webp 或 text/plain,Chrome 就会标记为 blocked:mime-type 并跳过该 <source>。
- 检查 CDN 回源响应头:用
curl -I https://cdn.example.com/photo.avif确认Content-Type: image/avif(注意大小写、无空格) - Nginx 或 Cloudflare Workers 中需显式设置
add_header Content-Type image/avif;,不能依赖文件扩展名自动推断 - 同一张图的不同格式(AVIF/WebP/JPEG)应使用不同文件名+相同路径结构,避免 CDN 因路径重复而混用缓存
sizes 属性写错,会让 CDN 下载的图根本用不上
如果 sizes="(max-width: 768px) 100vw",但实际 CSS 中该图只占 300px 宽,浏览器就会按 768px 宽度去选 srcset 里的图——比如拉一张 hero-1200w.jpg,而这张图在 CDN 缓存中存在,却远大于实际需要,浪费带宽也拖慢首屏。
立即学习“前端免费学习笔记(深入)”;
-
sizes值必须真实反映 CSS 布局结果,不是“想让它多大”,而是“它在各断点下渲染出来多大” - 用 Chrome DevTools → Elements → 查看 computed width,再反推
sizes表达式,例如:sizes="(max-width: 479px) 100vw, (max-width: 1023px) 50vw, 33vw" - CDN 不关心
sizes,但它决定了浏览器发什么宽度的请求——错的sizes= 错的请求 = 错的缓存键 = 白存一堆大图
多尺寸图的命名与路径设计要利于 CDN 缓存粒度控制
CDN 缓存是以完整 URL 为键的。如果你把所有尺寸都放在同一目录,比如 /img/hero-400w.jpg、/img/hero-800w.jpg,那它们就是独立缓存项;但若你用查询参数或哈希嵌套,就容易出问题。
- 推荐路径结构:
/img/hero/hero-400w.webp、/img/hero/hero-800w.webp—— 清晰、静态、易 purge - 避免:
/img/hero.webp?width=400(CDN 可能忽略 query)或/img/hero-400w.jpg?v=2.1(每次构建都失效) - 如果用内容哈希(如 Webpack 输出
hero.a1b2c3.webp),确保哈希只随内容变,不随构建时间或环境变,否则 CDN 缓存无法复用
最常被忽略的一点:CDN 不会帮你修复语法错误。哪怕你写了十层 <source>,只要其中任意一个 media 缺括号、type 大小写错、sizes 漏单位,浏览器就直接跳过全部,只加载 <img src>——而这张图很可能没走任何优化逻辑,连 CDN 缓存策略都白配。



















