preload

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Preload

Preload

Preload (
<link rel="preload">
) is a browser optimization that allows critical resources (that may be discovered late) to be requested earlier. If you are comfortable thinking about how to manually order the loading of your key resources, it can have a positive impact on loading performance and metrics in the Core Web Vitals. That said, preload is not a panacea and requires an awareness of some trade-offs.
Preload (
<link rel="preload">
) 是一种浏览器优化手段,允许提前请求那些可能被晚发现的关键资源。如果你熟悉如何手动安排关键资源的加载顺序,它可以对加载性能和Core Web Vitals中的指标产生积极影响。也就是说,Preload并非万能药,需要了解一些权衡取舍。

When to Use

使用场景

  • Use this when critical resources (fonts, scripts, images) are discovered late in the loading process
  • This is helpful for improving Time To Interactive (TTI) and Largest Contentful Paint (LCP)
  • 当关键资源(字体、脚本、图片)在加载过程中被晚发现时使用此方法
  • 这有助于提升Time To Interactive(TTI,首次交互时间)和Largest Contentful Paint(LCP,最大内容绘制)指标

Instructions

使用说明

  • Use
    <link rel="preload">
    for resources needed immediately on the current page
  • Be careful not to delay First Contentful Paint by preloading too many resources
  • Use
    as
    attribute to specify the resource type (script, style, font, image)
  • For fonts and other CORS-fetched resources, set
    crossorigin
    on the preload to match the eventual request mode
  • Only preload resources that must be visible within ~1 second of initial render
  • 对当前页面立即需要的资源使用
    <link rel="preload">
  • 注意不要因预加载过多资源而延迟First Contentful Paint(FCP,首次内容绘制)
  • 使用
    as
    属性指定资源类型(script、style、font、image)
  • 对于字体和其他跨域获取的资源,在预加载标签上设置
    crossorigin
    以匹配最终的请求模式
  • 仅预加载初始渲染后约1秒内必须可见的资源

Details

详细说明

html
<link rel="preload" href="emoji-picker.js" as="script">
...
</head>
<body>
  ...
  <script src="stickers.js" defer></script>
  <script src="video-sharing.js" defer></script>
  <script src="emoji-picker.js" defer></script>
When optimizing for metrics like Time To Interactive or First Input Delay, preload can be useful to load JavaScript bundles (or chunks) that are necessary for interactivity. Keep in mind that great care is needed when using preload as you want to avoid improving interactivity at the cost of delaying resources (like hero images or fonts) necessary for First Contentful Paint or Largest Contentful Paint.
If you are trying to optimize the loading of first-party JavaScript, you can also consider using
<script defer>
in the document
<head>
vs.
<body>
to help with early discover of these resources.
html
<link rel="preload" href="emoji-picker.js" as="script">
...
</head>
<body>
  ...
  <script src="stickers.js" defer></script>
  <script src="video-sharing.js" defer></script>
  <script src="emoji-picker.js" defer></script>
在针对Time To Interactive(TTI)或First Input Delay(FID,首次输入延迟)等指标进行优化时,Preload可用于加载交互所需的JavaScript包(或代码块)。请记住,使用Preload时需要格外谨慎,因为你要避免为了提升交互性而延迟FCP或LCP所需的资源(比如首屏图片或字体)。
如果你尝试优化第一方JavaScript的加载,还可以考虑在文档的
<head>
中使用
<script defer>
而非在
<body>
中使用,这有助于提前发现这些资源。

Preload in single-page apps

单页应用中的Preload

While prefetching is a great way to cache resources that may be requested some time soon, we can preload resources that need to be used instantly. Maybe it's a certain font that is used on the initial render, or certain images that the user sees right away.
Say our
EmojiPicker
component should be visible instantly on the initial render. Although it should not be included in the main bundle, it should get loaded in parallel. Just like prefetch, we can add a magic comment in order to let Webpack know that this module should be preloaded.
js
const EmojiPicker = import(/* webpackPreload: true */ "./EmojiPicker");
Webpack 4.6.0+ allows preloading of resources by adding
/* webpackPreload: true */
to the import. In order to make preloading work in older versions of webpack, you'll need to add the
preload-webpack-plugin
to your webpack config.
After building the application, we can see that the
EmojiPicker
will be preloaded.
 Asset                             Size       Chunks                          Chunk Names
    emoji-picker.bundle.js         1.49 KiB   emoji-picker [emitted]          emoji-picker
    vendors~emoji-picker.bundle.js 171 KiB    vendors~emoji-picker [emitted]  vendors~emoji-picker
    main.bundle.js                 1.34 MiB   main  [emitted]                 main

Entrypoint main = main.bundle.js
(preload: vendors~emoji-picker.bundle.js emoji-picker.bundle.js)
The actual output is visible as a
link
tag with
rel="preload"
in the
head
of our document.
html
<link rel="preload" href="emoji-picker.bundle.js" as="script" />
<link rel="preload" href="vendors~emoji-picker.bundle.js" as="script" />
The preloaded
EmojiPicker
could be loaded in parallel with the initial bundle. Unlike
prefetch
, where the browser still had a say in whether it thinks it's got a good enough internet connection and bandwidth to actually prefetch the resource, a preloaded resource will get preloaded no matter what.
Instead of having to wait until the
EmojiPicker
gets loaded after the initial render, the resource will be available to us instantly! As we're loading assets with smarter ordering, the initial loading time may increase significantly depending on your users device and internet connection. Only preload the resources that have to be visible ~1 second after the initial render.
虽然prefetching(预获取)是缓存近期可能需要的资源的好方法,但我们可以preload(预加载)需要立即使用的资源。比如初始渲染时使用的某个字体,或者用户立即就能看到的某些图片。
假设我们的
EmojiPicker
组件在初始渲染时需要立即显示。虽然它不应包含在主包中,但它应该被并行加载。就像prefetch一样,我们可以添加一个魔法注释,让Webpack知道这个模块应该被预加载。
js
const EmojiPicker = import(/* webpackPreload: true */ "./EmojiPicker");
Webpack 4.6.0+允许通过在import中添加
/* webpackPreload: true */
来预加载资源。要在旧版本的Webpack中实现预加载,你需要在webpack配置中添加
preload-webpack-plugin
构建应用后,我们可以看到
EmojiPicker
会被预加载。
 Asset                             Size       Chunks                          Chunk Names
    emoji-picker.bundle.js         1.49 KiB   emoji-picker [emitted]          emoji-picker
    vendors~emoji-picker.bundle.js 171 KiB    vendors~emoji-picker [emitted]  vendors~emoji-picker
    main.bundle.js                 1.34 MiB   main  [emitted]                 main

Entrypoint main = main.bundle.js
(preload: vendors~emoji-picker.bundle.js emoji-picker.bundle.js)
实际输出会在文档的
head
中显示为带有
rel="preload"
link
标签。
html
<link rel="preload" href="emoji-picker.bundle.js" as="script" />
<link rel="preload" href="vendors~emoji-picker.bundle.js" as="script" />
预加载的
EmojiPicker
可以与初始包并行加载。与
prefetch
不同,浏览器是否预获取资源取决于它认为自身的网络连接和带宽是否足够,而preload的资源无论如何都会被预加载。
我们无需等到初始渲染后再加载
EmojiPicker
,资源会立即可用!由于我们以更智能的顺序加载资源,初始加载时间可能会根据用户的设备和网络连接显著增加。仅预加载初始渲染后约1秒内必须可见的资源。

Preload + the
async
hack

Preload +
async
技巧

Should you wish for browsers to download a script as high-priority, but not block the parser waiting for a script, you can take advantage of the preload + async hack below. The download of other resources may be delayed by the preload in this case, but this is a trade-off a developer has to make:
html
<link rel="preload" href="emoji-picker.js" as="script">
<script src="emoji-picker.js" async>
如果你希望浏览器以高优先级下载脚本,但又不想让脚本阻塞解析器,可以使用下面的Preload + async技巧。在这种情况下,预加载可能会延迟其他资源的下载,但这是开发者必须做出的权衡:
html
<link rel="preload" href="emoji-picker.js" as="script">
<script src="emoji-picker.js" async>

Font preloads must use
crossorigin

字体预加载必须使用
crossorigin

Fonts are fetched as CORS resources, even when they are self-hosted on the same origin. This means the preload request and the eventual
@font-face
request need to use the same fetch mode, or the preload cannot be reused.
If you preload a font without
crossorigin
, the browser will typically make a
no-cors
preload request and later a separate
cors
request when CSS discovers the font. That leads to a double fetch of the same file and wastes bandwidth.
Avoid:
html
<link rel="preload" href="/fonts/inter-roman.woff2" as="font" type="font/woff2">
Prefer:
html
<link
  rel="preload"
  href="/fonts/inter-roman.woff2"
  as="font"
  type="font/woff2"
  crossorigin
>
And make sure the
@font-face
matches the same resource:
css
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-roman.woff2") format("woff2");
  font-display: swap;
}
This same rule applies more broadly: if the eventual consumer fetches a resource with CORS semantics, the preload should match that mode too.
字体是作为跨域资源获取的,即使它们托管在同一源上。这意味着预加载请求和最终的
@font-face
请求需要使用相同的获取模式,否则预加载无法被复用。
如果你预加载字体使用
crossorigin
,浏览器通常会发起一个
no-cors
预加载请求,之后当CSS发现字体时又会发起一个单独的
cors
请求。这会导致同一文件被两次获取,浪费带宽。
避免:
html
<link rel="preload" href="/fonts/inter-roman.woff2" as="font" type="font/woff2">
推荐:
html
<link
  rel="preload"
  href="/fonts/inter-roman.woff2"
  as="font"
  type="font/woff2"
  crossorigin
>
并确保
@font-face
指向相同的资源:
css
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-roman.woff2") format("woff2");
  font-display: swap;
}
同样的规则也适用于更广泛的场景:如果最终的资源获取使用跨域语义,预加载也应匹配该模式。

Preload in Chrome 95+

Chrome 95+中的Preload

Thanks to some fixes to preload's queue-jumping behavior in Chrome 95+, the feature is slightly safer to use more broadly. Pat Meenan of Chrome's new recommendations for preload suggest:
  • Putting it in HTTP headers will jump ahead of everything else
  • Generally, preloads will load in the order the parser gets to them for anything >= Medium so be careful putting preloads at the beginning of the HTML.
  • Font preloads are probably best towards the end of the head or beginning of the body
  • Import preloads should be done after the script tag that needs the import (so the actual script gets loaded/parsed first)
  • Image preloads will have a low priority and should be ordered relative to async scripts and other low/lowest priority tags
得益于Chrome 95+中对Preload的队列跳转行为的一些修复,该功能在更广泛的场景下使用会更安全。Chrome的Pat Meenan针对Preload提出了新建议:
  • 将其放在HTTP头中会优先于所有其他资源;
  • 一般来说,对于优先级>=中等的资源,预加载会按照解析器遇到它们的顺序加载,因此要谨慎将预加载标签放在HTML的开头;
  • 字体预加载最好放在
    head
    的末尾或
    body
    的开头;
  • 导入预加载应在需要该导入的脚本标签之后进行(这样实际脚本会先被加载/解析);
  • 图片预加载的优先级较低,应相对于异步脚本和其他低/最低优先级标签进行排序;

Conclusions

结论

Again, use preload sparingly and always measure its impact in production. If the preload for your image is earlier in the document than it is, this can help browsers discover it (and order relative to other resources). When used incorrectly, preloading can cause your image to delay First Contentful Paint (e.g CSS, Fonts) - the opposite of what you want. Also note that for such reprioritization efforts to be effective, it also depends on servers prioritizing requests correctly.
You may also find
<link rel="preload">
to be helpful for cases where you need to fetch scripts without executing them.
A variety of web.dev articles touch on how to use Preload to:
再次强调,要谨慎使用Preload,并始终在生产环境中衡量其影响。如果图片的预加载标签在文档中的位置比图片本身早,这可以帮助浏览器发现它(并相对于其他资源排序)。如果使用不当,预加载可能会导致图片延迟FCP(比如CSS、字体)——这与你的预期相反。还要注意,这种重新排序的努力要有效,还取决于服务器是否正确地对请求进行优先级排序
你可能还会发现
<link rel="preload">
在需要获取脚本但不执行的情况下很有用。
web.dev上的多篇文章介绍了如何使用Preload来:

Source

来源