根本原因是浏览器未将preload请求识别为字体:as="font"缺失、crossorigin漏写或href与@font-face的src路径不一致,任一错误均导致预加载失效,Initiator显示parser、Priority为Low或请求被cancelled。
根本原因不是没写 rel="preload",而是浏览器压根没把它当字体用——as="font" 缺失、crossorigin 漏掉、或 href 和 @font-face 中的 src 路径不一致,三者任一出错,预加载就形同虚设。
常见现象:Network 面板里字体请求 Initiator 显示 parser 而非 preload,Priority 是 Low,甚至 Status 为 cancelled。这不是缓存问题,是浏览器从一开始就没按字体逻辑处理这个请求。
as="font" 必须显式声明,写成 as="woff2" 或留空,浏览器直接降级为普通 fetchcrossorigin 属性必须存在(值可为空),哪怕字体和 HTML 同源——字体加载默认走匿名 CORS 模式,缺它就丢弃已下载内容href 必须和 @font-face 的 src 完全一致:包括协议、域名、路径、查询参数(如 ?v=2.1),差一个字符就无法复用缓存不是越全越好,而是刚好够用。以下是最简且可靠的写法,适用于 WOFF2 字体:
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/inter-bold.woff2">
对应 CSS 中必须有匹配的 @font-face:
立即学习“前端免费学习笔记(深入)”;
@font-face { font-family: 'Inter'; font-weight: 700; src: url('/fonts/inter-bold.woff2') format('woff2');}
type="font/woff2" 推荐带上,避免 MIME 类型探测失败;服务端返回的 Content-Type 必须与之匹配onload 或其他 JS 控制逻辑——字体不需要“激活”,只要 @font-face 注册成功且文本用到该字体,浏览器会自动从缓存取href 必须带完整域名(如 https://cdn.example.com/fonts/...),不能只写相对路径预加载不是“所有字重都来一遍”的保险操作,而是精准狙击首屏实际渲染所用的变体。多 preload 一个文件,就多占一次 TCP 连接、多耗一次带宽、多挤占真正关键资源的优先级。
font-weight: 400,标题用 font-weight: 700,那就只 preload 这两个 WOFF2 文件italic、light、thin 等未在首屏 CSS 中出现的变体——它们可能永远不被触发family=Inter:[email protected] 做批量 preload,拆解成单个 href 并只选真实用到的权重@font-face 保持完全一致,否则缓存无法命中别信代码写了,要看 Network 面板里那个请求是不是真被浏览器当回事儿。重点盯三列:Initiator、Priority、Time。
type: font,再按 Initiator 列找 preload —— 如果是 parser 或 script,说明没走预加载路径Priority 应为 Highest(Chrome)或 High(Firefox),不是 Low;Low 意味着 as 错了或缺失Access-Control-Allow-Origin: *)Accept 请求头是否为 font/woff2,响应头 Content-Type 是否匹配,不匹配就不会复用最易被忽略的是:服务端返回 302 重定向或 Cache-Control: no-store,会导致预加载结果无法用于后续渲染——这种失效不会报错,只表现为反复下载。