把
<link>
标签玩出花,让首屏快、下一跳更快,还省 DNS 时间。全文没有废话,直接给「能复制」的代码和「能量化」的对比数据。
一、为什么要关心这"三兄弟"
指标 | 未优化 | 优化后(示例数据) |
---|---|---|
FCP(首屏) | 1.8 s | 1.2 s ⬇33% |
下一跳 JS 加载 | 350 ms | 0 ms(disk cache) |
CDN 域名解析 | 210 ms | 95 ms ⬇54% |
成本 :只加几行 HTML,0 业务逻辑改动,不升级框架、不花钱买 CDN 流量。
二、能力矩阵(先收藏,再对照)
特性 | 作用对象 | 优先级 | 生命周期 | 典型场景 |
---|---|---|---|---|
preload | 当前页关键子资源 | 高(与 CSS/JS 并行) | 当前 Tab | 字体、首屏大图、关键脚本 |
prefetch | 下一跳页面/资源 | 最低(浏览器空闲) | 5 min disk cache | 列表→详情、路由懒加载、WebAssembly |
dns-prefetch | 跨域域名 | 仅 DNS | 20-120 ms 节省 | 第三方 CDN、统计、API 网关 |
一句话口诀:
首屏要命用 preload,下一跳用 prefetch,跨域先 dns-prefetch。
三、实战 1:字体白屏------preload 直接插队
问题
自定义字体写在 CSS 里,浏览器要等 CSS 下载完才发现字体,再发请求 → FCP 被拖慢。
解决
把字体请求提前到 HTML,让字体与 CSS 并行加载。
html
<!-- index.html <head> 顶部 -->
<link rel="preload"
href="/fonts/AlibabaPuHui-3.0-Bold-subset.woff2"
as="font"
type="font/woff2"
crossorigin>
注意
① as="font"
必写,否则浏览器不知道优先级;
② 字体必须加 crossorigin
,否则会重复下载。
效果
本地 4G 慢网(Chrome DevTools 3 次平均):
FCP 从 1.8 s → 1.2 s,直接砍 33%。
四、实战 2:列表→详情,提前把 JS 偷回来
技术栈
Vue3 + Vite + Vue-Router 懒加载(Webpack 同理)。
目标
用户在列表页停留 >300 ms 就把详情页脚本 prefetch 进磁盘缓存。
步骤
- 路由文件加魔法注释
js
// router.js
const ProductDetail = () => import(
/* webpackChunkName: "product-detail" */
/* webpackPrefetch: true */ // 关键行
'@/views/ProductDetail.vue'
)
- 构建后自动插入(无需手写)
html
<link rel="prefetch" href="/js/product-detail.17aa7b89.js">
- 验证
列表页→Network→Priority: Lowest →闲时下载;
点击进入详情→JS size=0 ms(from disk cache),首屏秒出。
踩坑提醒
不要把首屏脚本也 webpackPrefetch:true
,会抢带宽,反而拖慢主流程。
五、实战 3:CDN 域名提前解析------省 100 ms DNS
背景
主站 www.xxx.com
,静态资源在 static.xxxcdn.com
;海外用户 DNS 延迟高。
代码
在入口 HTML 最顶部(任何资源之前):
html
<head>
<meta charset="utf-8">
<!-- 1. 先解析 CDN 域名 -->
<link rel="dns-prefetch" href="//static.xxxcdn.com">
<!-- 2. HTTPS 可再激进一点,直接预连 -->
<link rel="preconnect" href="//static.xxxcdn.com" crossorigin>
</head>
线上数据 (WebPageTest 北美节点):
DNS Time 从 210 ms → 95 ms ;
后续所有 static.xxxcdn.com
资源整体左移 ≈110 ms。
六、常见踩坑清单(血泪总结)
- preload 不写
as
→ 浏览器当普通 HTML 下载,优先级丢失。 - 字体 preload 漏
crossorigin
→ 重复下载,流量 double。 - 把首屏大图也 prefetch → 闲时带宽被占,FCP 反而涨。
- dns-prefetch 写同域 → 毫无效果,还浪费解析线程。
- 弱网环境 prefetch 命中率低,且
Cache-Control: no-cache
时直接浪费流量,需评估。
七、一条命令验证效果
bash
# 本地起静态服务器,模拟慢网
npx http-server dist -p 8080 -d 200 # 200ms 延迟
Chrome DevTools → Network →
- Priority 列:preload 资源显示 High ;prefetch 显示 Lowest。
- Size 列:prefetch 资源第二次访问显示 (disk cache)。
八、速查表(复制即可用)
html
<!-- 1. 首屏关键字体 -->
<link rel="preload" href="/fonts/xx.woff2" as="font" type="font/woff2" crossorigin>
<!-- 2. 列表→详情(Webpack/Vite 魔法注释自动生成,无需手写) -->
<!-- 3. 第三方 CDN / 统计域名 -->
<link rel="dns-prefetch" href="//static.xxxcdn.com">
<link rel="preconnect" href="//static.xxxcdn.com" crossorigin>
九、结语
性能优化 ≠ 大刀阔斧重构,几行 <link>
就能换 30% 的 FCP 提升 。
下次评审再被挑战"首屏慢",直接把这篇甩给他------复制、粘贴、测一遍,立省 100 ms。
如果帮到你,点个「赞」再走;
想深挖更多"零成本"优化,留言告诉我!