你的网站还在让用户干等吗?

别让访客在白屏前数秒针。
点开页面那几秒,不是加载进度条,而是用户耐心的倒计时。

预加载(Preload)到底是什么?它如何工作?

浏览器加载网页,其实是一场“按图索骥”的接力赛:先读 HTML,再根据里面写的 <link><script> 去找 CSS、JS、图片……这个过程有先后、有依赖、有等待。

预加载 rel="preload" 就是提前递一张纸条给浏览器:“这几个文件,别等我读到才去拿,现在就去搬,放门口等着。”

它不改变页面结构,也不执行代码,只是把资源下载这件事,往前挪——挪到 HTML 解析刚开始的时候,甚至更早。

一个真实的对比:
我们优化过一个电商详情页。原来用户点进来,要等 CSS 先下载完、解析完、开始渲染,才轮到主图和交互 JS。结果就是:文字先出来,图片慢半拍,点按钮没反应,得等一秒才动。
加了两行 preload 后,主图和核心 JS 几乎和 CSS 同时启动下载。用户看到文字的同时,主图也快出来了;点“加入购物车”,按钮响应立刻跟上——那种“点了但没反应”的迟滞感,消失了。

哪些资源最适合用预加载来提速?

预加载不是万能胶水,贴多了反而糊住自己。它只该用在真正卡脖子的地方。

首当其冲:自定义字体文件。
比如你用了 Google Fonts 或自己托管的 .woff2 字体。浏览器默认会等字体下载完才渲染文字,造成空白或闪烁。预加载能让字体“插队”,文字一出来就有样儿。

其次是首屏最大内容元素(LCP)对应的资源。
比如文章顶部的 banner 图、产品页的主图、首页的视频封面。用户第一眼看到什么,就优先加载什么。

还有那些“一上来就要用”的 JS。
比如控制轮播图、商品尺码选择、搜索框自动补全的脚本。它们不一定是体积最大的,但没它们,用户根本没法操作。

别碰这些:
折叠区以下的图片、懒加载的组件、后台统计脚本、通用工具库——它们不该抢首屏的带宽。

如何正确实施预加载?3个核心方法

方法一:直接写进 HTML <head>

最稳、最直观,兼容所有现代浏览器。
在你网站的 <head> 里加几行:

<link rel="preload" href="/fonts/inter-bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/images/hero-banner.jpg" as="image">
<link rel="preload" href="/js/main.4a2b.js" as="script">

关键点:

  • as 必须写对(image / script / font / style);
  • 加载字体时,crossorigin 不能少,哪怕字体在自己服务器上;
  • 路径用绝对路径或根相对路径,避免部署后 404。

方法二:用 HTTP 响应头

适合用 Nginx、Vercel、Cloudflare Pages 或后端框架(如 Express、Django)管理静态资源的团队。
在服务器配置里加上这行响应头:

Link: </css/critical.css>; rel=preload; as=style

好处是:指令比 HTML 更早到达浏览器,连 HTML 文件本身都还没开始解析,下载就已经开始了。

方法三:用 JavaScript 动态插入

适合需要“看人下菜”的场景:比如用户鼠标悬停在某个菜单项上,才预加载对应二级页面的资源。
代码很简单:

const link = document.createElement('link');
link.rel = 'preload';
link.as = 'script';
link.href = '/js/product-detail.js';
document.head.appendChild(link);

注意:JS 执行有延迟,它不如前两种“够早”,所以只用于明确的条件触发场景。

预加载实践中,你最容易踩进哪些坑?

坑一:漏写或写错 as 属性

只写 <link rel="preload" href="...">,没写 as?浏览器会把它当普通请求,优先级拉到最低,等于白加。
更糟的是:如果把图片写成 as="script",浏览器可能拒绝加载,或者加载失败后重试,反而拖慢整体。

坑二:预加载了“用不上的东西”

为首页预加载了“关于我们”页的背景视频?为移动端页面预加载了桌面端高清图?这些请求占着网络通道,却对当前用户毫无意义。
预加载不是“越多越好”,而是“刚刚好”。

坑三:字体跨域不加 crossorigin

从 CDN 加载字体时,漏掉 crossorigin 是高频翻车现场。浏览器会预加载一次(失败),等到 CSS 里真正引用时,再重新发起一次请求——等于下了两遍,还白耗时间。

真实翻车案例:
一个资讯站一口气预加载了 8 张首屏大图,每张 2MB+。结果这些高优请求把网络打满,CSS 和 JS 反而排在后面,首屏渲染时间不降反升。后来只保留最关键的 banner 图 + 标题字体,LCP 时间缩短了不少,滚动也顺了。

除了Preload,还有哪些“预”字诀法宝?

它们不是替代品,而是搭档。

rel="prefetch":为“下一步”悄悄备货。
比如用户正在看一篇教程,你大概率猜他接下来要点“下一章”。那就 prefetch 下一章的 HTML 和关键资源。它优先级低,不影响当前页,但真点进去时,快得像本地跳转。

rel="preconnect":提前打通第三方“大门”。
如果你用了 Google Fonts、微信 SDK、阿里云 OSS,每个新域名都要走 DNS → TCP → TLS 三步。加一行:

<link rel="preconnect" href="https://fonts.googleapis.com">

就能省下几百毫秒握手时间,尤其对弱网用户很实在。

rel="dns-prefetch":只做第一步——查 DNS。
preconnect 更轻量,适合你暂时不确定要不要连,但知道可能会连的域名。

rel="prerender":慎用!
它会在后台完整加载并执行另一个页面(包括 JS)。只建议用在转化路径极确定的环节,比如支付成功页。多数网站用不上,还容易吃光内存。

今天下班前,你就可以完成这个优化动作

不用改架构,不用等排期,15 分钟搞定。

第一步:打开你的网站首页,用 Chrome 或 Edge 浏览器。
右键 → “检查” → 切到“网络”(Network)标签页 → 勾上“禁用缓存”(Disable cache)→ 刷新页面。

第二步:在瀑布流里,找这三个东西:

  • 字体文件(.woff2.ttf),看它是不是卡在最后才开始下载;
  • 首屏最大的那张图(通常叫 hero.jpgbanner.png);
  • 一个 JS 文件,名字里带 mainappcore,且它的“启动时间”明显晚于 HTML。

第三步:复制下面这段代码,粘贴到你网站 HTML 模板的 <head> 里(WordPress 用户:编辑主题的 header.php;Vue/React 项目:找到 public/index.html):

<link rel="preload" href="/fonts/your-font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/images/your-hero.jpg" as="image">

href 里的路径替换成你第二步找到的真实地址。

第四步:保存,上线,再刷一次页面。
回到“网络”面板,对比前后:被预加载的资源,启动时间(左边竖线)是不是明显左移了?LCP 元素出现得是不是更快了?
如果看到了变化——恭喜,你刚亲手给用户省下了几秒等待。