字体preload不起作用的根本原因是浏览器将字体存入fetch缓存而非font缓存池,因as="font"漏crossorigin、href与@font-face src路径不一致、服务端缺失immutable响应头或type不匹配,导致后续@font-face无法复用。

为什么字体 preload 不起作用,但 Network 里能看到请求
常见现象是:写了 <link rel="preload" href="/fonts/inter.woff2" as="font">,Network 面板里确实有请求、状态码 200,但刷新后还是 FOIT(文字不可见),甚至第二次加载仍没复用缓存。根本原因不是“没加载”,而是浏览器把字体塞进了 fetch 缓存,而非 font 缓存池——后续 @font-face 请求无法命中。
-
as="font"漏了crossorigin属性 → Chrome/Safari 直接丢弃已加载字形,不进 font 缓存(哪怕同源也必须加) -
href和@font-face src字符串不一致 → 差一个斜杠、大小写、查询参数(如?v=1.2),就被视为不同资源 - 服务端没返回
Cache-Control: public, immutable, max-age=31536000→ 即使路径全对,下次导航也可能重拉 -
type值和服务端实际 MIME 类型不匹配(如服务端返回font/woff2,但写了type="font/woff")→ 缓存校验失败
字体 preload 的正确写法和配套动作
只写一行 <link> 不够,必须四点齐备才能真正生效:
-
as="font"+crossorigin必须同时出现,crossorigin值可为空或"anonymous",但不能省略 -
href必须和 CSS 中@font-face的src完全一致(建议统一用根相对路径,如/fonts/inter-latin.woff2) - CSS 中
@font-face必须配font-display: swap,否则即使预加载完成,浏览器仍会阻塞文本渲染 - 服务端响应头至少含:
Cache-Control: public, immutable, max-age=31536000;字体尤其依赖immutable,它告诉浏览器“此文件永不变更”
如何验证字体 preload 真正起效
不能只看 HTML 有没有那行代码,也不能只看 Network 是否发起请求。关键看三处:
- 在 Chrome DevTools → Network 面板,筛选
Initiator = preload,确认该请求的Priority列显示为Highest(不是Low) - 刷新页面后,找到对应字体请求,
Status列应为200 (from memory cache)或304;若仍是200且无(from memory cache),说明未命中 font 缓存 - 打开 Application → Cache Storage → 找到
Font Cache(Chrome 115+ 支持),搜索字体文件名,确认其存在其中;若只出现在Memory Cache或HTTP Cache,就不是 font 缓存
容易被忽略的兼容性细节
字体 preload 在 Safari 和旧版 Chrome 上行为更严格,稍有偏差就退化:
- Firefox 不强制要求
crossorigin,但 Chrome/Safari 会直接丢弃预加载结果 → 必须加 -
as="font"不支持media属性,响应式字体需靠 JS 动态插入不同<link>,不能靠 media 查询 - 如果用了
font-display: optional,即使 preload 成功,浏览器也可能跳过加载 → 首屏字体推荐用swap - Webpack/Vite 构建时若自动哈希字体文件名(如
inter-abc123.woff2),务必确保href和@font-face src使用同一哈希值,否则路径必然不一致
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











