Published on

性能优化篇(四) : Prefetch

翻译至: Prefetch

此系列文章:

性能优化篇(一) : 分包

性能优化篇(二) : 压缩Javascript

性能优化篇(三) : 动态导入

性能优化篇(五) : Preload

性能优化篇(六) : PRPL模式

性能优化篇(七) : Tree Shaking

Prefetch

预取(Prefetch) ( <link rel="prefetch"> ) 是一种浏览器优化,它允许我们在后续路由或页面需要之前获取它们可能需要的资源。预取可以通过几种方式实现。

它可以通过 HTTP 标头 ( Link: </js/chat-widget.js>; rel=prefetch )、Service Workers 或通过更多自定义方式(例如通过 Webpack)以 HTML 声明方式完成(例如下面的示例)。

<link rel="prefetch" href="/pages/next-page.html" />
<link rel="prefetch" href="/js/emoji-picker.js" />

在展示如何根据可见性或交互导入模块的示例中,我们发现单击按钮以切换组件与在屏幕上显示实际组件之间通常存在一些延迟。发生这种情况是因为当用户单击按钮时仍然需要请求并加载模块。

在许多情况下,我们知道用户会在页面初始渲染后不久会请求某些资源。因为它们不需要显示首屏中,所以不应包含在初始Bundle包中,不过如果能够可能减少该模块加载时间以提供更好的用户体验,那就太好了!

我们知道可能会在应用程序中的某个时刻使用的组件或资源可以被预取。我们可以通过在 import 语句中添加一个神奇的注释: /* webpackPrefetch: true */ 来让 Webpack 知道某些包需要预取。

const EmojiPicker = import(/* webpackPrefetch: true */ "./EmojiPicker");

构建应用程序后,我们可以看到 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
(prefetch: vendors~emoji-picker.bundle.js emoji-picker.bundle.js)

实际输出在文档的 head 中显示为带有 rel="prefetch" 的 link 标记。

<link rel="prefetch" href="emoji-picker.bundle.js" as="script" />
<link rel="prefetch" href="vendors~emoji-picker.bundle.js" as="script" />

甚至在用户请求资源之前,浏览器就会请求并加载Prefetch的模块。当浏览器空闲并计算出它有足够的带宽时,它会发出请求以加载资源并缓存它。

缓存资源可以显着减少加载时间,因为我们不需要在用户单击按钮后等待资源请求完成。它可以简单地从缓存中获取加载的资源。

尽管预取是优化加载时间的好方法,但不要过度使用。如果用户最终从未请求 <EmojiPicker> 组件,则我们不必要地加载资源。这可能会花费用户耐心,或者减慢应用程序的速度。仅预取必要的资源。

参考:

Preload, Prefetch And Priorities in Chrome

web.dev pfetching

What (not) to Prefetch/Prerender