rel="preload"是强制高优先级加载当前页关键资源,解析到即发起请求;rel="prefetch"是低优先级预取后续页资源,仅空闲时加载,不提升当前页性能,两者语义、时机和用途完全不同。

什么是 rel="preload",它和 rel="prefetch" 有啥区别?
rel="preload" 是浏览器强制提前获取资源的指令,告诉浏览器“这个资源马上就要用,现在就去下载”,且不执行、不解析;而 rel="prefetch" 是提示“这个资源将来可能用到(比如下一页),空闲时再下”。两者语义不同,混用会导致资源浪费或阻塞渲染。
-
rel="preload"必须配合as属性(如as="script"、as="font"),否则浏览器无法判断资源类型,可能忽略或降级处理 - 它只对当前页面生命周期有效,不会跨页面缓存复用
- 不支持
crossorigin的字体资源若没配对设置,会触发两次请求(一次预加载失败,一次实际使用) -
rel="prefetch"没有as要求,但优先级低,常被浏览器丢弃,尤其在弱网或内存紧张时
怎么写一个安全有效的 <link rel="preload">?
关键不是“写了就行”,而是让浏览器真正按预期加载。漏掉 as、类型错配、路径错误都会让预加载失效。
-
as值必须与实际资源类型严格一致:JS 用as="script",CSS 用as="style",woff2 字体用as="font"(注意不是"font/woff2") - 字体必须加
crossorigin属性,哪怕同源:<link rel="preload" href="fonts/abc.woff2" as="font" crossorigin> - 避免预加载未压缩的资源(如
.js却没开 Gzip/Brotli),浏览器可能因 Content-Length 判断为低优先级而延迟加载 - 不要预加载内联
<script>或动态import()里的模块,这些无法被静态<link>覆盖
preload 加载失败时浏览器会怎么反应?
它不会报错,也不会 fallback,只是静默跳过——这是最容易被忽视的风险点。
- 控制台看不到明显错误,但 Network 面板里该请求状态可能是
cancelled或pending长时间不动 - 常见诱因:路径 404、MIME 类型不匹配(如服务器返回
text/plain却声明as="script")、CSP 策略拦截、HTTPS 页面加载 HTTP 资源(混合内容) - 浏览器不会重试,也不会影响后续真实请求;也就是说,即使预加载失败,页面仍会照常发起第二次请求,相当于白跑一趟还占带宽
- 可用
PerformanceObserver监听resource类型条目,检查initiatorType为"preload"的条目是否duration > 0,来间接验证是否生效
哪些资源适合预加载,哪些其实不该动?
预加载不是性能银弹,用错比不用更伤。
立即学习“前端免费学习笔记(深入)”;
- 推荐:关键 CSS(
as="style")、首屏 JS(as="script")、核心 Web Font(as="font"+crossorigin)、关键图片(as="image",需配合fetchpriority="high") - 慎用:第三方脚本(CDN 不稳定、缓存策略不可控)、体积 > 100KB 的资源(可能挤占关键资源带宽)、非首屏组件的懒加载模块(应交给
import()或 IntersectionObserver) - 禁止:HTML 文档本身(
as="document"无效)、base64 data URL(浏览器不支持预加载 base64)、未声明 MIME 的服务器响应(如无Content-Type头)
实际部署前,一定要在 Chrome DevTools 的 Network → “Disable cache” + “Throttling” 下观察预加载请求是否出现在早期 Waterfall 中,且状态为 200 和 from disk cache(如果是重复访问)。否则就是配置没生效,或者资源根本没被复用。



















