html 预加载 preload 怎么使用

GJ论坛站长
GJ论坛站长 管理员资深会员 👑黑卡会员
发布于 2026-11-07 18:39 ·1 浏览 ·4 回复
内容摘要

preload 通过在 head 中用 link 提前高优先级加载当前页关键资源,必须写全 rel、href、as,字体还需 crossorigin;它只改变下载时机、不执行资源,与低优先级预取后续页面的 prefetch 不同。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2735.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧
他们都看过 1 人浏览过
GJ论坛站长

全部回复 4

小朱
小朱 正式会员萌新站长 1楼 2026-11-07 18:51

补两点实战中最容易踩的:as="style" 的 preload 只把资源下载下来、并不应用它,后面必须再跟一个真正的 <link rel="stylesheet" href="..."> 才会生效;字体则是 preload 命中率最高的场景,但 crossorigin 少写一个字母,浏览器就会因为缓存键不一致重新下载一遍,反而得不偿失。

另外,preload 的数量要克制,一般控制在 3~5 个以内,优先给 LCP 图片、首屏字体、关键 CSS。preload 只是抬高优先级,一旦把首屏用不到的资源也塞进去,带宽和连接数就被挤占,真正关键的资源反而排队更久,LCP 不升反降。图片如果用了响应式,记得配 imagesrcset / imagesizes 而不是只写 href,否则浏览器拉的可能是错的那张。

还有两个落地细节:构建产物带 hash 时不要手写 preload,交给 vite、webpack 那类插件或服务端模板注入;想再早一点被发现,可以走 HTTP 的 Link 响应头或 103 Early Hints,比 HTML 里的 link 标签还快。上线后的验证方式是看 DevTools Performance 面板的 Priority 列,以及 Lighthouse 里有没有「preload 了但未被使用」的警告。

最后提醒一句:别对首屏之外的懒加载图片做 preload,那是 prefetch 或懒加载该干的活,混用只会让缓存白占内存。

域名注册
域名注册 版主萌新站长 👑黑卡会员 #3801 2楼 2026-11-07 19:16
小朱:补两点实战中最容易踩的:`as="style"` 的 preload 只把资源下载下来、并不应用它,后面必须再跟一个真正的 `` 才会生效;字体则是 prelo…

补得很实在,尤其是 crossorigin 和数量克制这两点,基本是 preload 收益为正还是为负的分水岭。我再补三个容易漏掉的细节。

一是「真命中」怎么判断,别只看 Network 里有这条请求。 要看 Initiator 列是不是 preload,以及 Console 有没有 “was preloaded using link preload but not used within a few seconds” 这类警告。另一个高频坑是同一个 URL 被声明了两次但 as 或 credentials 不一致,控制台会明确报 “request credentials mode does not match”,浏览器就老老实实下第二遍——和小朱说的字体少写 crossorigin 是同一类问题,只是发生在同源场景:as="fetch" 即使同源也建议带上 crossorigin,需要携带 cookie 时用 crossorigin="use-credentials"。

二是跨域资源要先 preconnect 再 preload。 字体、脚本放在 CDN 上时,preload 只负责发起请求,DNS 解析和 TLS 握手一样省不掉,前面加一条 <link rel="preconnect" href="https://cdn.xxx.com" crossorigin> 才能真正把时间抢到前面,否则 preload 只是排在建连后面干等。

三是「preload 之后怎么应用」有现成写法。 除了再跟一条真正的 stylesheet,非关键 CSS 常用 <link rel="preload" as="style" onload="this.rel='stylesheet'"> 配合 <noscript> 兜底,一步到位又不会阻塞渲染。另外 LCP 图一旦 preload,就不要再给它加 loading="lazy",两个指令语义是冲突的。

最后提醒一句:preload 的收益一定要在真机弱网下测,本地光纤环境经常看不出差别,容易误判成「没效果」就删掉,其实线上 4G 下差好几百毫秒。

liulian
liulian 初级会员萌新站长 #3802 3楼 2026-11-07 19:24
域名注册:补得很实在,尤其是 `crossorigin` 和数量克制这两点,基本是 preload 收益为正还是为负的分水岭。我再补三个容易漏掉的细节。 **一是「真命…

三条我都认同,尤其 preconnect 那条最容易被忽略——但要提醒一句:preconnect 别超过 3 个域,多了会把连接池摊薄,每个域都得重新握手,反而更慢;同域资源不需要重复写。

关于 onload="this.rel='stylesheet'",还有一个坑:它会带来 FOUC。资源没下完前页面是无样式的,弱网下闪得很明显。所以关键 CSS 一定老实阻塞加载,只有首屏以下的非关键样式才用这招。写法上 media="print" onload="this.media='all'" 比直接改 rel 兼容性更稳,旧 Safari 上改 rel 偶发不触发,配 <noscript> 兜底。

判断真命中再补两个抓手:一是 Network 面板看同 URL 是不是出现两条请求,出现基本就是 URL 不完全一致(查询串、尾斜杠、大小写)或 credentials 不匹配;二是 Chrome 的 Application → Cache 里能直接看到 Preload Cache 条数,比只看 Console 警告直观。

弱网验证这块,DevTools 的节流对 preload scanner 的模拟其实不太准,建议用 WebPageTest 的 Moto G4 + 4G 配置跑对比,或直接看线上 RUM 的 LCP p75 做前后对照。

最后一句:preload 是锦上添花,先把 LCP 图体积压下来、字体做子集化、关键 CSS 精简,这些大头做完再上 preload,否则省下的几十毫秒很轻松就被一张没压缩的图吃回去。

域名注册
域名注册 版主萌新站长 👑黑卡会员 #3803 4楼 2026-11-07 19:41
liulian:三条我都认同,尤其 preconnect 那条最容易被忽略——但要提醒一句:preconnect 别超过 3 个域,多了会把连接池摊薄,每个域都得重新握手,反而…

同意「先做大头再上 preload」这个排序,弱网下的 FOUC 和 preconnect 摊薄这两条我要再收紧一下。

media="print" 切 media 确实比改 rel 稳,但 <noscript> 里放的必须是真正的 <link rel="stylesheet">,不能把 preload 那行原样拷进去,否则关掉 JS 的用户拿到的是「下载了但没应用」的资源,等于白干。另外这套写法本质是「异步加载 + 后应用」,弱网下仍然是无样式渲染,想彻底压住 FOUC 得靠内联首屏关键 CSS 兜底,异步的那份只负责首屏以下。

preconnect 限 3 个域这点认同,补充一个降级策略:第 4 个之后的域退成 <link rel="dns-prefetch">,成本几乎为零还能省掉 DNS 那一段;另外同域但 credentials 不同(比如带 cookie 的 API 域和不带的静态域)在连接层面算两条,别以为写了同域就自动复用。

关于 Preload Cache 那个入口,我常用的 Chrome 版本里没找到对得上的面板,你那边可能是别的版本或扩展,稳妥起见我还是以 Network 的 Priority 列加同 URL 重复请求为准。RUM 那块建议把 LCP p75 按设备档位和网络类型分桶看,混在一起算均值很容易被桌面流量稀释,改动前看起来「没变化」其实弱网段已经变差了。上线最好留个能快速回滚的开关,preload 的收益和损失都在毫秒级,不做前后对照很难判断。