彻底搞懂 Preload:为什么必须加 as?从底层机制到工程化最佳实践的全链路解析

133 阅读4分钟

彻底搞懂 <link rel="preload">:为什么必须声明 as,以及它与 Prefetch 的本质区别

在性能优化中,很多开发者知道 preload 可以“加速加载” ,却不知道 as 是 preload 生效的关键。甚至大量线上项目因为 缺失 as 或 as 错配 反而出现 重复请求、带宽浪费、字体无法复用、首屏变慢 等“性能倒退”。

本文从实际工程角度,系统讲清 preload 的核心机制、浏览器如何利用 as、常见错误、最佳实践,并补充最容易混淆的 preload vs prefetch 区别,确保你能将它真正用在生产环境中。


一、核心结论(直击本质)

<link rel="preload"> 不是“提前执行”,而是告诉浏览器:

这个资源非常关键,请尽快下载,但先不要执行/应用。

而要让浏览器在后续真正使用该资源时 复用这次下载的结果,就必须告诉浏览器:

  • 这是 脚本 / 样式 / 字体 / 图片 / fetch 请求 / worker
  • 它的用途是什么
  • 应用什么优先级、安全策略、缓存分区

这一切都由 as 属性决定

如果 as 错配或缺失,浏览器就会认为这是一个 无类型资源,导致:

  • 下载优先级下降
  • 与实际用途的缓存不匹配 → 二次请求
  • 字体因缺少 CORS 规则而失效
  • 模块脚本无法复用,甚至拒绝执行

换句话说:

preload 是否真正提升性能,90% 取决于 as 是否正确。


二、浏览器为什么需要 as(底层机制讲透)

浏览器会根据 as 做四件关键事情:

1. 决定请求优先级(Loading Priority)

不同资源优先级不同:

资源类型优先级
样式最高(影响渲染)
脚本
字体
图片
prefetch最低

没有 as → 浏览器无法判定 → 预加载意义大幅下降。


2. 应用正确的安全策略 / CORS

例如:

  • 字体 preload:必须携带 crossorigin
  • 脚本 preload:需要按照脚本安全规则处理
  • fetch preload:会按 CORS 规则处理请求

无 as → 无法匹配正确策略 → 完成下载却无法复用。


3. 放入正确的缓存“分区”(Fetch group)

浏览器会根据 request destination 存放缓存:

  • as="script" → 归类为脚本缓存
  • as="style" → 样式缓存
  • as="font" → 字体缓存
  • as="image" → 图像缓存

如果 preload 没有 as:

→ 浏览器会将其归类为“无类型”缓存
→ 后续真正加载时 不匹配,无法复用
重新请求一次

这是许多站点出现 重复请求 的根本原因。


4. MIME 预期与错误保护

预加载字体时浏览器预期 font/woff2
预加载脚本预期 application/javascript

类型不符 → 直接拒绝复用。


三、一些简单的示例

预加载脚本(最常见)

<link rel="preload" href="/static/app.js" as="script">
<script src="/static/app.js" defer></script>

预加载样式

<link rel="preload" href="/css/main.css" as="style">
<link rel="stylesheet" href="/css/main.css">

预加载字体(必须加 crossorigin)

<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>

预加载关键图片(谨慎使用)

<link rel="preload" href="/img/hero.jpg" as="image">

四、错误使用 as 会带来哪些严重后果?

下载优先级错误

CSS 或 JS 被当成“低优先级资源”,导致首屏变慢。

缓存不匹配导致重复请求

Network 面板常见的“双份下载”就是这里来的。

字体下载了但无法被 CSS 使用

最典型表现:FOIT / FOUT 现象加重。

带宽浪费、关键资源受阻

尤其是 HTTP/1 上,会严重阻塞关键请求。


五、Preload 与 Prefetch 的区别(最容易混淆,但非常重要)

一图看懂 Preload vs Prefetch

项目PreloadPrefetch
用途加速“当前页面”关键资源提前下载“未来页面”可能需要的资源
优先级高(参与渲染关键路径)极低(不会影响当前页面)
是否立即使用是,将在当前渲染中用到否,未来可能用到
资源缓存是否可复用高概率复用通常复用
会不会阻塞当前页面可能绝不会
示例资源CSS、JS、字体、首屏图像下一跳页面的脚本、图片、JSON

直观理解

  • Preload = 当前页面的加速器
  • Prefetch = 下一个页面的缓存预热器

如果你把本该 prefetch 的资源 preload → 影响当前首屏
如果把本该 preload 的资源 prefetch → 毫无效果

这是工程上最常见的误区之一。


六、工程化最佳实践

  • 只 preload 关键渲染资源(CSS、关键 JS、字体)
  • preload font 时 必须加 crossorigin + type
  • preload CSS 后仍需 <link rel="stylesheet">
  • 模块脚本优先使用 rel="modulepreload"
  • 不要滥用 preload(会拖慢首屏)
  • preload 必须放在 <head> 顶部
  • 经常检查浏览器是否出现“二次请求”

八、总结

Preload 让浏览器“提前知道”关键资源是什么;
as 让浏览器“提前知道”它要如何被正确处理。
二者缺一不可,否则 preload 不但无效,还可能拖慢性能。