必须手动预加载WebP与JPEG路径,主格式加fetchpriority="high",fallback不加或设为low;需运行时检测格式支持、路径严格对应、避免CDN/Service Worker缓存污染,且注意并发请求限制。

用 <link rel="preload"> 预加载 WebP + JPEG fallback 时必须手动控制路径
浏览器不支持自动格式协商预加载,<link rel="preload"> 的 href 是单值,不能像 <picture> 那样写多个 source。你得自己决定:哪个格式是主选,哪个是兜底,且两者都得显式声明。
常见错误是只预加载 WebP 却没管 JPEG,结果 Safari(不支持 WebP 的旧版)或某些 CDN 缓存节点回源失败时,图片直接 404;或者写了两个 <link> 但没区分优先级,导致低优先级的 JPEG 抢占了带宽。
- 主格式(如 WebP)加
fetchpriority="high",确保首屏关键图优先下载 - fallback 格式(如 JPEG)不加
fetchpriority,或用fetchpriority="low"(Chrome 115+),避免挤占关键资源 - 路径必须一一对应:如果最终
<img src="/assets/hero.webp">,那预加载的href就得是/assets/hero.webp,不能写成/assets/hero.jpg后指望浏览器“自动替换” - 不要依赖服务端内容协商(如 Accept 头)——
<link>发起的请求不携带完整 Accept 图片类型列表,服务器无法可靠判断该返回哪个格式
new Image() 动态预加载前必须先检测格式支持
运行时根据 HTMLCanvasElement.prototype.toBlob 或 document.createElement('source').canPlayType('image/webp') 判断是否支持 WebP,再决定调用 new Image() 加载哪个 URL。否则在不支持 WebP 的设备上预加载 .webp 就是白跑一次请求,还占缓存位置。
注意:Safari 直到 16.4 才全面支持 WebP,iOS 16.0–16.3 仅部分支持;Android WebView 的 WebP 支持率虽高,但部分定制 ROM 仍可能禁用。
立即学习“前端免费学习笔记(深入)”;
- 检测逻辑要早于预加载触发点,比如放在
DOMContentLoaded回调里,而不是用户 hover 后才检测 - 检测函数应缓存结果,避免重复调用——
canPlayType不是纯函数,但对固定 MIME 类型返回稳定值 - fallback 加载失败时,别静默吞掉错误:
onerror触发后应降级尝试 JPEG 路径,而非放弃 - URL 构造需一致:WebP 路径为
/assets/hero.webp,JPEG 就得是/assets/hero.jpg,不能混用 hash 后缀或 query 参数(如?v=2),否则缓存不共享
多格式预加载会放大并发请求数限制风险
每个 <link rel="preload"> 算一个独立请求,每个 new Image() 实例也占一个 TCP 连接槽位。Chrome 默认并发数约 6,HTTP/2 下略高,但若同时预加载 WebP + JPEG + AVIF 三版本,就直接吃满连接池,可能阻塞 JS、CSS 下载。
这不是理论问题——真实页面中,轮播图每张图都配三格式,再叠加 banner、头像、icon,很容易超限。尤其移动端弱网下,连接复用效率更低。
- 优先保 WebP(覆盖 98%+ 主流浏览器),AVIF 暂不预加载(兼容性差,编码成本高)
- 非首屏资源(如下一页轮播图)只预加载一种格式,用 JS 检测到支持后再补 fallback
- 用
Promise.allSettled包裹批量预加载,避免单个失败阻断整体流程 - 检查 Network 面板里的 “Waterfall”,确认预加载请求没被标记为 “blocked” 或 “stalled”
CDN 和 Service Worker 对多格式预加载的影响常被忽略
很多团队开了 CDN 的“自动 WebP 转换”,以为只要传 JPEG,CDN 就能返回 WebP 给支持的客户端——但这对 <link rel="preload"> 无效。因为 preload 请求的 Accept 头极简(通常只有 text/html),CDN 无法识别客户端图片格式偏好,大概率原样返回 JPEG,导致缓存污染。
Service Worker 更麻烦:如果你 intercept 了图片请求并做格式重写,但没同步处理 preload 的 fetch,就会出现“预加载进缓存的是 JPEG,实际渲染时却 fetch WebP”,缓存失效。
- CDN 场景下,预加载必须用真实存在的文件路径,关闭“自动格式转换”或明确配置规则(如
/assets/*.webp → origin /assets/*.jpg) - Service Worker 中需监听
fetch事件,对匹配destination: 'image'的请求统一处理,且 preload 请求和后续 img.src 请求必须走同一套逻辑 - 本地开发时,用
curl -H "Accept: image/webp,*/*"测试 CDN 返回,别只看浏览器 Network 面板



















