根本原因是浏览器将 rel="preload" 和 rel="stylesheet" 视为两个独立请求,即使 href 相同也不会自动复用;只有 as="style"、href 完全一致且 onload 中动态切换 rel 为 "stylesheet" 才能真正复用。

为什么 rel="preload" 和 rel="stylesheet" 同时写会重复请求
根本原因:浏览器把它们当成两个独立资源请求,即使 href 完全相同,也不会自动复用 preload 下载结果——除非你主动干预 rel 值切换。
- preload 只触发下载,不解析、不挂载,也不影响后续
link[rel="stylesheet"]的行为 - 浏览器不会“看到 preload 已经下好了,就跳过 stylesheet 的请求”,它照常发起第二个请求
- 只有当 preload 的
as正确(as="style")、路径完全一致(含查询参数)、且 onload 中把this.rel改成"stylesheet"时,才真正复用已下载内容 - 如果用了
media="print"临时隐藏再切回all,也必须确保两次的href字符串完全相等,否则仍会重发
as="style" 写错或漏掉的后果
写成 as="stylesheet"、as="fetch" 或直接省略 as,浏览器就无法识别这是样式资源,降级为普通 fetch 请求:
- 请求头 Accept 不是
text/css,服务端可能返回错误 Content-Type - 不进样式专用缓存池,后续
link[rel="stylesheet"]无法命中复用 - 优先级被设为 Low 或 Medium,抢不过首屏图片或 JS,失去预加载意义
- DevTools Network 面板里看不到 Priority 为 Highest/High,Initiator 也显示为 Parser 而非 preload
路径不一致导致的隐性重复
哪怕只是查询参数不同,浏览器就认为是两个资源。比如:
- preload 的
href="main.css?v=1.2",但页面中link[rel="stylesheet"]的 href 是"main.css?v=1.2.1"→ 重复请求 - CSS 文件内 @import 的子文件路径,和你手动 preload 的路径大小写/斜杠不一致(如
/fonts/Inter.woff2vs/fonts/inter.woff2)→ 字体也无法复用 - 构建工具自动注入哈希(如
main.a1b2c3.css),但你手写的 preload 还是main.css→ 白忙活
真正避免重复的关键动作
不是“少写一个标签”,而是让 preload 成为 stylesheet 的前置状态:
- 必须写
as="style",不能写错或省略 - 必须用
onload="this.onload=null;this.rel='stylesheet'"动态切换,this.onload=null必须放最前,防 SPA 路由复用时多次执行 - preload 和最终生效的 stylesheet 标签,
href字符串必须逐字节一致(包括协议、域名、路径、查询参数、编码) - 服务端响应头不能是
Cache-Control: no-cache,否则 Chrome 会直接跳过 preload
最容易被忽略的是:preload 解决的是“发现晚”,不是“资源复用”。它不自动绑定后续任何标签——绑定动作得你亲手写在 onload 里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











