Prefetch (<link rel="prefetch">
) 是一种浏览器优化,它允许我们在需要后续路由或页面之前获取可能需要的资源。可以通过几种方式实现预取。它可以在 HTML 中以声明方式完成(例如在下面的示例中),通过 HTTP 头(Link: </js/chat-widget.js>; rel=prefetch
)、Service Workers 或通过更自定义的方式(例如通过 Webpack)。
<link rel="prefetch" href="/pages/next-page.html" />
<link rel="prefetch" href="/js/emoji-picker.js" />
在展示如何根据可见性或交互导入模块的示例中,我们看到在单击按钮以切换组件和在屏幕上显示实际组件之间经常存在一些延迟。发生这种情况,因为当用户单击按钮时,模块仍然必须被请求和加载!
在许多情况下,我们知道用户会在页面初始呈现后不久请求某些资源。尽管它们可能无法立即显示,因此不应包含在初始 bundle 包中,但尽可能减少加载时间以提供更好的用户体验会很棒!
我们知道可能在应用程序中的某个时间点使用的组件或资源可以预取。我们可以通过在 import 语句中添加一个神奇的注释来让 Webpack 知道某些 bundle 需要预取: /* webpackPrefetch: true */
。
const EmojiPicker = import(/* webpackPrefetch: true */ "./EmojiPicker");
// ChatInput.js
import React, { Suspense, lazy } from "react";
import Send from "./icons/Send";
import Emoji from "./icons/Emoji";
const EmojiPicker = lazy(() =>
import(/*webpackPrefetch: true,
webpackChunkName: "emoji-picker"*/
"./EmojiPicker")
);
const ChatInput = ({ emojiPicker, gifPicker }) => {
const [pickerOpen, togglePicker] = React.useReducer(state => !state, false);
return (
<div className="chat-input-container">
<input type="text" placeholder="Type a message..." />
<Emoji onClick={togglePicker} />
{pickerOpen && (
<Suspense fallback={<p id="loading">loading</p>}>
<EmojiPicker />
</Suspense>
)}
<Send />
</div>
);
};
console.log("ChatInput loading", Date.now());
export default ChatInput;
构建应用程序后,我们可以看到 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" />
浏览器甚至在用户请求资源之前就请求和加载预取的模块。当浏览器处于空闲状态并计算出它有足够的带宽时,它将发出请求以加载资源并缓存它。缓存资源可以显著减少加载时间,因为我们不必在用户单击按钮后等待请求完成。它可以简单地从缓存中获取加载的资源。