C03 资源提示与性能

2026-10-31 14:490 阅读约 11 分钟HTML

摘要:首屏时间的大部分消耗在「发现资源」与「等待连接」两步,而不是解析 HTML。preconnect、preload、fetchpriority 与 defer 这四类声明,作用是把这两步提前或推后。用错方向时收益为负:预加载不用的资源会挤占带宽,阻塞脚本会推迟首屏。本文给出按关键路径配置的四段代码与三项验证。
关键词:关键渲染路径,preload,preconnect,fetchpriority,阻塞

所属:frontend/html / C-高级 | 上一篇:C02-表单校验进阶 | 下一篇:C04-XSS与CSP

1 引言

页面变慢有两种原因:资源太多,或资源发现得太晚。前者的解法是压缩与裁剪,后者的解法是资源提示——让浏览器在解析到对应标签之前就知道「有个东西要提前拿」。

本文按关键路径的顺序给出四段声明与取舍依据。范围见表 1-1。

项 本文覆盖 本文不覆盖
连接 dns-prefetch、preconnect CDN 与边缘节点选型
资源 preload、prefetch、fetchpriority、modulepreload 打包与代码分割策略
脚本 defer、async、type="module" 框架水合与运行时性能
字体与图片 font-display、宽高预留、懒加载边界 字体子集化与图片编码

2 预备知识

项 要求 核对方式
环境 A02 的本地服务器 能访问 localhost
前置 B02、B01 图片与 head 已掌握
工具 Chrome 开发者工具 Performance 与 Network 面板 能看到瀑布图与优先级
文件 html-practice/perf.html 编码 UTF-8

3 原理与实现

3.1 关键路径与提示位置

浏览器按「建立连接 → 发现资源 → 下载 → 解析 → 渲染」推进,资源提示插在前两步,如图 3-1 所示。

flowchart LR
    A["HTML 到达"] --> B["解析 head"]
    B --> C["dns-prefetch / preconnect<br/>提前建连"]
    B --> D["preload<br/>提前发现关键资源"]
    B --> E["脚本 defer / async<br/>调整执行时机"]
    D --> F["下载关键 CSS 与字体"]
    E --> G["DOMContentLoaded"]
    F --> H["首次绘制"]
    G --> H
    H --> I["可交互"]

图 3-1 关键渲染路径与资源提示的位置

图上可见:提示只改变「什么时候开始下载」,不改变资源体积;体积问题必须靠压缩与裁剪解决。

3.2 四段声明

<!-- 运行环境:Chrome 130+;head 内按需使用 -->
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <!-- 1. 提前建连:第三方域名 -->
  <link rel="preconnect" href="https://cdn.example.com" crossorigin />
  <link rel="dns-prefetch" href="https://cdn.example.com" />

  <!-- 2. 提前发现:首屏关键资源 -->
  <link rel="preload" href="./assets/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
  <link rel="preload" href="./assets/images/hero.avif" as="image" fetchpriority="high" />

  <!-- 3. 非首屏资源:空闲时再取 -->
  <link rel="prefetch" href="./assets/images/next-page.jpg" as="image" />

  <!-- 4. 脚本时机 -->
  <script src="./assets/js/app.js" defer></script>
  <script src="./assets/js/analytics.js" async></script>
</head>

<body>
  <img src="./assets/images/hero.avif" alt="首屏主图" width="1200" height="630" fetchpriority="high" decoding="async" />
  <img src="./assets/images/cover.avif" alt="文章配图" width="960" height="540" loading="lazy" decoding="async" />
</body>

四类提示的差异见表 3-1。

声明 提前做什么 过度使用后的代价
dns-prefetch 域名解析 几乎无代价,可多加
preconnect DNS + TCP + TLS 占用连接,超过 4 个反而变慢
preload 下载并缓存指定资源 与其它资源抢带宽,未使用会告警
prefetch 空闲时下载下个页面资源 流量浪费,弱网下拖慢当前页
fetchpriority 调整同类型资源的优先级 全部标 high 等于没有优先级
defer 解析完 HTML 后按顺序执行 首屏依赖该脚本时会延后渲染
async 下载完立即执行 执行顺序不可控

常见指标与对应手段见表 3-2。

指标 含义 主要手段
LCP 最大内容绘制时间 首屏图预加载 + fetchpriority="high"
CLS 布局偏移 图片与广告位预留宽高
INP 交互响应 减少主线程长任务,脚本 defer
TTFB 首字节时间 连接复用、服务端缓存

4 验证与讨论

  1. 打开 Network 面板,勾选 Priority 列,记录首屏图与懒加载图的优先级差异。
  2. 打开 Performance 面板录制一次加载,查看 LCP 标记落在哪个元素上,是否为首屏图。
  3. 删除 width / height,重复步骤 2,观察 CLS 是否出现偏移。
  4. 把 defer 改为同步脚本,比较首次绘制时间的变化。
检查项 预期结果 说明
连接复用 第三方域名提前建连 瀑布图起点提前
首屏图优先级 标记为 High fetchpriority
懒加载图 初始不请求 loading="lazy"
布局稳定 CLS 接近 0 宽高预留
脚本不阻塞 首屏在脚本下载前已绘制 defer

讨论与局限。 preload 的资源若最终未被使用,浏览器会给出未使用告警,且浪费一次请求。另本地开发环境没有网络延迟,资源提示的收益在本地几乎不可见,必须用限速模拟或真实网络验证。

5 常见问题

现象 原因 处理
preload 告警未使用 资源地址与页面实际请求不一致 与 src 完全一致,含 crossorigin 设置
字体仍闪烁 未用 font-display 或 preload 缺失 补 font-display: swap 与 preload
首屏图优先级未提升 写在了 srcset 的候选上 在 img 元素上加 fetchpriority
加了 async 后脚本报错 依赖顺序被打乱 改 defer 或合并脚本
CLS 偏高 图片与占位容器无固定尺寸 补宽高或用宽高比容器

6 结论

序号 结论 依据
1 资源提示改变发现与连接时机,不改体积 图 3-1
2 preconnect 控制在 4 个以内 表 3-1
3 首屏图 fetchpriority="high",其余懒加载 表 3-1、3.2 代码
4 布局稳定靠宽高预留,不靠提示 表 3-2

参考文献

[1] MDN Web Docs · 资源提示,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Attributes/rel/preload(访问于 2026-10-29)
[2] web.dev · 优化 LCP,https://web.dev/articles/optimize-lcp(访问于 2026-10-29)

返回文章列表

评论 0

0/2000

还没有评论,快来抢沙发吧~