【免费下载链接】Front-End-Checklist
🗂 The essential checklist for modern web development, for humans and AI agents
Resource hints(资源提示)让浏览器在常规 HTML 解析流程之外提前发现关键资源,从而显著缩短首屏加载的关键路径。本文基于 Front-End-Checklist 仓库中 performance-resource-hints 技能文档及其 references/rule.md 参考文档,系统讲解 preload、prefetch、preconnect、dns-prefetch 四种提示的适用场景、决策规则、框架级写法与验证方法,并对照仓库源码说明实际项目中的落地方式。读完本文,你将掌握如何针对自己的站点判断"该提示什么、不该提示什么",并用瀑布图数据验证优化是否真正生效。
什么是 Resource Hints,为什么它们能加速加载
浏览器的 HTML 解析器是按顺序发现资源的:CSS 文件中引用的字体要等 CSS 被解析之后才会被请求,首屏图片要等<img>标签被解析到才会开始下载。这种"串行发现"会让关键路径上出现不必要的等待。
Resource hints 通过<link rel="...">标签向浏览器提供"提前预告",让它在资源被正常解析发现之前就启动 DNS 查询、TCP 连接、TLS 握手甚至完整下载。正如参考文档 references/rule.md 所言:资源提示只有在"浏览器原本会发现得太晚"时才真正有用——它只在你用对了时机、命中了正确的资源时才加速,用错了反而比不加提示更糟。
Front-End-Checklist 将这条规则归类为performance/loading子类别,优先级为high、难度intermediate、预估耗时20 分钟,对应的内容规则文件位于 packages/content/rules/en/performance/resource-hints.mdx,其中列出了四条快速参考要点:
- 用
preload加载首屏关键资源(字体、首屏图); - 用
preconnect建立第三方源(CDN、API、分析服务)的早期连接; - 用
prefetch预取下一次导航很可能需要的资源; - 用
dns-prefetch作为preconnect的轻量替代。
平均而言,合理的资源提示可以让 LCP(Largest Contentful Paint)提升约 100–300ms。
四种 Hint 的本质区别与决策规则
preload、prefetch、preconnect、dns-prefetch对应浏览器加载流程中不同深度的"预热"动作:
| Hint | 用途 | 应避免的场景 | 实用上限 |
|---|---|---|---|
preload | 当前路由、首屏绘制或 LCP 需要但发现得太晚的资源 | 未来路由的资产、低优先级组件、已被及早发现的资源 | 每条路由通常不超过 3–5 个 |
prefetch | 下一个路由或下一次交互很可能会用、但当前并不必须的资源 | 当前路由的关键资产;对带宽敏感用户且下一步不确定时 | 只针对最可能的下一个导航目标 |
preconnect | 确定即将使用的源,尤其是字体、媒体 CDN 或首屏路由上的 API | 投机性的第三方、很久以后才用的源 | 通常不超过 2–4 个源 |
dns-prefetch | 置信度较低的外部源,此时完整建连为时过早 | 已在关键路径上、值得完整preconnect的源 | 作为轻量回退,而非无差别默认 |
这张决策表同样出现在 references/rule.md 和 content 规则 中,是整条规则的核心。它的要点是:提示的层级越深(从 dns-prefetch 到 preconnect 到 preload),消耗的资源越多,因此只应该为置信度越高的资源使用。
dns-prefetch:只做 DNS 解析,开销最小,适合"可能用但不确定"的源;preconnect:DNS + TCP + TLS 全链路建连,适合"确定马上要用"的第三方源;prefetch:以低优先级提前拉取资源到缓存,适合"下一步大概率会用"的资产;preload:以高优先级立即获取资源,适合"当前页面关键路径上、但发现太晚"的资产。
仓库还提供了独立的 preconnect 技能,进一步强调:preconnect 只在外部落源确定需要在首屏附近使用、且建连开销原本会落在关键路径上时才有效;对于可能用也可能不用的源,应优先选择dns-prefetch。
实战一:用 preload 加速当前路由的关键资产
preload告诉浏览器"这个资源现在就重要,请立刻以高优先级获取"。两个最典型的场景是 LCP 候选图和字体。
<head> <!-- Good: hero image is the likely LCP candidate --> <link rel="preload" href="/images/hero.webp" as="image" type="image/webp" fetchpriority="high" > <!-- Good: route-critical font discovered late through CSS --> <link rel="preload" href="/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin > </head>几个属性值得注意:
as:声明资源类型(image、font、script、style、document等),浏览器据此决定请求优先级与缓存复用。缺少as会让 preload 失去优先级意义,还可能产生重复请求。type:声明 MIME 类型,帮助浏览器跳过不需要的下载(例如只支持 WebP 的场景)。crossorigin:字体资源的 preload 必须携带crossorigin,否则会触发双重请求(一次 no-cors、一次 cors)。fetchpriority="high":进一步提升 LCP 候选图的请求优先级。
参考文档 references/rule.md 特别给出了反模式示例——同一页面堆了 6 个字体/脚本 preload 和 3 个投机性 preconnect:
<head> <!-- Bad: too many preloads compete with each other --> <link rel="preload" href="/fonts/a.woff2" as="font" crossorigin> <link rel="preload" href="/fonts/b.woff2" as="font" crossorigin> <link rel="preload" href="/fonts/c.woff2" as="font" crossorigin> <link rel="preload" href="/carousel.js" as="script"> <link rel="preload" href="/reviews.js" as="script"> <link rel="preload" href="/chat-widget.js" as="script"> <!-- Bad: speculative origins do not deserve early socket setup --> <link rel="preconnect" href="https://chat.example.com"> <link rel="preconnect" href="https://ads.example.com"> <link rel="preconnect" href="https://social.example.com"> </head>过多的 preload 会彼此争抢带宽与解析器注意力,反而拖慢真正重要的 CSS、字体和 LCP 资源;对只在交互后才会用到的聊天、广告、社交组件做 preconnect 则纯属浪费连接预算。
实战二:用 prefetch 预热下一次导航
prefetch以低优先级提前拉取"下一个很可能的步骤",让后续导航"感觉是瞬时的"。关键区分在于:prefetch 服务于未来路由,而不是当前路由。
<head> <!-- Good: likely next navigation --> <link rel="prefetch" href="/checkout"> <link rel="prefetch" href="/static/checkout.js" as="script"> <!-- Bad: current-route critical CSS should be loaded normally or preloaded --> <link rel="prefetch" href="/styles/home.css" as="style"> </head>对当前路由的关键 CSS 使用 prefetch 是错误的:它不会进入关键路径的优先级队列,只是给网络平添噪音。另外也不应 prefetch 当前已经打开的页面,那不会改善发现顺序。
除了静态标签,也可以在交互时动态注入 prefetch 提示,例如鼠标悬停到导航链接时再预取目标页(hover 场景置信度高,值得预取),参见 html-resource-hints 参考文档 中的 JS 示例:
// Prefetch routes the user is likely to visit // Can be triggered on hover for high confidence navLinks.forEach(link => { link.addEventListener('mouseenter', () => { const prefetch = document.createElement('link') prefetch.rel = 'prefetch' prefetch.href = link.href document.head.appendChild(prefetch) }, { once: true }) })实战三:用 preconnect 与 dns-prefetch 处理第三方源
第三方源(Google Fonts、媒体 CDN、API、分析平台)的建连开销——DNS 查询、TCP 握手、TLS 协商——往往都在关键路径上。preconnect可以把这些步骤提前到首屏资源真正发起请求之前完成。
<head> <!-- Good: fonts are used in the first viewport --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <!-- Good: image CDN serves the hero media --> <link rel="preconnect" href="https://images.example-cdn.com" crossorigin> <!-- Better than preconnect for speculative vendors --> <link rel="dns-prefetch" href="https://analytics.example.com"> </head>使用要点:
- 字体源必须带
crossorigin(字体通过 CORS 获取); - 只对"当前路由确定会用、且在首屏附近"的源做 preconnect,通常控制在 2–4 个;
- 对分析、标签管理等"可能用但不确定"的源,
dns-prefetch(仅做 DNS 解析)是比完整preconnect更划算的选择,如https://www.googletagmanager.com这类域名; - 同源资源通常收益有限,因为浏览器对同源已有成熟的连接复用策略,preconnect 主要针对第三方。
preconnect 技能文档 归纳了同样的决策规则:仅当外部源确定在当前路由、且大约在首屏之前或附近需要时使用preconnect;源只是"可能"时优先dns-prefetch;每条页面控制在 2–4 个高价值源;对字体等 CORS 资源带上crossorigin。
为什么它重要:收益与代价
参考文档 references/rule.md 列出了四个层面的影响:
- 更早发现真正关键的资源:preload 可以让首屏图、字体、路由关键 CSS 更早进入网络;
- 减少浪费的往返:preconnect 可以从关键路径上移除少数已知外部源的 DNS、TCP、TLS 建连;
- 后续动作更平滑:prefetch 让下一个路由或交互"感觉即时";
- 误用代价高昂:每一个多余的 preload、prefetch、preconnect 都会与更重要的工作争抢带宽、socket 和解析器注意力。
html-resource-hints 参考文档 还给出了一个直观的量化:为关键字体增加一条 preload 指令,可以消除 100–300ms 的 FOIT(Flash of Invisible Text,字体加载期间的文字不可见闪烁)。这是因为浏览器原本要等 CSS 解析完才发现字体,而 preload 打破了这条依赖链,让字体获取与解析并行。
框架级落地:HTML、Vite、Next.js 与 React
参考文档与 content 规则 提供了多框架示例,核心写法如下。
原生 HTML(也适用于 Vite 项目的 index.html):
<head> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin> </head>Next.js(App Router 的 Root Layout):
import type { ReactNode } from 'react' export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="en"> <head> <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" /> <link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossOrigin="anonymous" /> </head> <body>{children}</body> </html> ) }React(配合 react-helmet 管理 head):
import { Helmet } from 'react-helmet' function PricingPage() { return ( <Helmet> <link rel="prefetch" href="/signup" /> <link rel="prefetch" href="/static/signup.js" as="script" /> </Helmet> ) }值得注意的是,Front-End-Checklist 自身在 Next.js 应用 apps/web/app/layout.tsx 中通过next/font/google自托管 Sora、Public_Sans、Fira_Code 三套字体:
const sora = Sora({ variable: '--font-sora', subsets: ['latin'], display: 'swap' })next/font会自动为这些字体生成preload与preconnect提示(包括crossorigin与display: swap配置),这正是"用框架能力替代手写资源提示"的实践路径:手写提示容易遗漏crossorigin、as等属性,而框架级 API 把正确性内建在工具链里。你也可以在代码审查时核对next/font生成的 HTML 来验证提示是否齐全。
常见错误清单
综合 references/rule.md 与 html-resource-hints,最常见的五类错误是:
- preload 了当前路由并不需要的资源:从 CSS、字体和 LCP 资源上偷走带宽;
- prefetch 了当前已经打开的页面:不改善发现顺序,只会增加噪音;
- preconnect 了太多源:为每个供应商都提前打开 socket,浪费连接预算与电量;
- 漏写
as或crossorigin:属性错误会降低优先级判断精度,或触发重复请求(字体双重下载); - 跳过测量:资源提示只有在瀑布图确实按预期变化时才有意义,改完必须验证。
另外还有一条频率极高的具体错误:字体 preload 漏掉crossorigin导致双重下载,以及对首屏后 2 秒内用不到的资源过度 preload——每个 preload 都在争抢带宽,只 preload 真正必要的东西。
如何验证:自动化检查与手动检查
资源提示优化是否生效,不能靠"感觉",必须回到测量数据。参考文档 references/rule.md 给出了标准的验证流程。
自动化检查:
- 用 Lighthouse、PageSpeed Insights 或浏览器 DevTools 测量受影响页面,确认目标指标(LCP、TTFB 等)确实提升;
- 检查 Network 瀑布图或 Performance 时间线,确认预期的资源/执行变化真正发生了;
- Lighthouse 中有专门的 "preconnect-to-required-origins" 审计,可用来发现缺失的 preconnect;
- WebPageTest 的 Waterfall 视图可以直观看到 DNS/TCP/TLS 是否被提前。
手动检查:
- 在节流的移动端 profile 下验证(不只是本地桌面环境),因为桌面网络往往掩盖建连开销;
- 如果该规则对应某个性能预算或 Web Vital 阈值,确认页面现在保持在阈值之内;
- 对最终渲染出的 HTML(浏览器页面源码)核验提示标签确实存在且属性完整。
总结
Resource hints 的核心方法论可以浓缩为一句话:只在"资源发现得太晚"处提示,提示的力度(dns-prefetch → preconnect → prefetch → preload)与资源的重要性、置信度成正比。preload 服务当前路由的关键资产,prefetch 预热下一次导航,preconnect 为确定要用的第三方源提前建连,dns-prefetch 为不确定的源做轻量准备——而每一步都要以瀑布图数据为最终裁判。
如果你正在审计慢页面加载,建议同时关联仓库中的相关规则一并复查:lazy-loading、lazy-above-fold、fetchpriority-attribute与third-party-scripts(见 content 规则元数据)。它们同属performance/loading区域,与资源提示共同构成完整的加载性能优化链路。完整的技能定义与快速参考可见 skills/performance-resource-hints/SKILL.md,HTML 侧的补充细节可参考 skills/html-resource-hints/references/rule.md,preconnect 专项规则见 skills/preconnect/SKILL.md。
【免费下载链接】Front-End-Checklist
🗂 The essential checklist for modern web development, for humans and AI agents
相关推荐
Front-End-Checklist 前端性能指南:preload、prefetch、preconnect 与 dns-prefetch 资源提示(Resource Hints)完整实战
Front End Checklist 前端性能指南:preload、prefetch、preconnect 与 dns prefetch 资源提示(Resou
Front-End-Checklist 资源提示(Resource Hints)实战指南:用 preload / prefetch / preconnect 将 LCP 提前 100-300ms
Front End Checklist 资源提示(Resource Hints)实战指南:用 preload / prefetch / preconnect 将
Front-End-Checklist 性能规则实战:用 preload、prefetch、preconnect 与 dns-prefetch 精确控制资源加载优先级
Front End Checklist 性能规则实战:用 preload、prefetch、preconnect 与 dns prefetch 精确控制资源加载
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考