Next.js 中的路由预提取

Next.js 如何通过路线预提取加快导航速度以及如何对其进行自定义。

Milica Mihajlija
Milica Mihajlija

您将学到什么?

在本文中,您将了解 Next.js 中的路由的工作原理、如何针对速度进行优化,以及如何对其进行自定义以最好地满足您的需求。

Next.js 中,您无需手动设置路由。 Next.js 使用基于文件系统的路由,让您可以直接创建文件和文件夹 ./pages/ 目录中:

包含以下三个文件的 Pages 目录的屏幕截图:index.js、margherita.js 和 pineapple-pizza.js。

要链接到不同的网页,请使用 <Link> 组件,类似于在 请使用合适的旧 <a> 元素:

<Link href="/margherita">
  <a>Margherita</a>
</Link>

当您使用 <Link> 组件进行导航时,Next.js 会执行一些操作 。通常,点击网页链接后就会下载该网页,但 Next.js 会自动预提取呈现网页所需的 JavaScript。

如果您加载的网页包含若干链接 表示链接后面的组件已被提取。这样可以改善 更快地导航到新页面,提高应用响应速度。

在下面的示例应用中,index.js 页面使用margherita.js <Link>:

使用 Chrome 开发者工具验证 margherita.js 是否已预提取: 1.如需预览网站,请按查看应用。然后按 全屏 全屏

  1. 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。

  3. 选中停用缓存复选框。

  4. 重新加载页面。

加载 index.js 时,Network 标签页会显示 margherita.js

突出显示了 margherita.js 的开发者工具“网络”标签页。

自动预提取的工作原理

Next.js 仅预提取显示在视口中的链接,并使用交集 Observer API 来检测它们。还会在网速较慢时停用预提取 或者 Save-Data 。根据这些检查,Next.js 会动态注入 <link rel="preload"> 标记,以便下载适用于 后续导航。

Next.js 只抓取 JavaScript;它不会执行它这样的话, 在您打开预提取页面之前, 链接。

避免不必要的预提取

为避免下载不必要的内容,您可以停用预先抓取功能, 在 <Link> 上将 prefetch 属性设置为 false

<Link href="/pineapple-pizza" prefetch={false}>
  <a>Pineapple pizza</a>
</Link>

在第二个示例应用中,index.js 页面有一个 <Link>,用于 prefetch 设置为 falsepineapple-pizza.js

如需检查网络活动,请按照第一个示例中的步骤操作。时间 加载 index.js 后,开发者工具的 Network 标签页显示 margherita.js 已下载,但 pineapple-pizza.js 未:

突出显示了 margherita.js 的开发者工具“网络”标签页。

使用自定义路由进行预提取

<Link> 组件适用于大多数用例,但您也可以构建 以及你自己的组件执行路由操作借助 Next.js next/router 中提供了 Router API。 如果您想执行某项操作(例如提交表单),然后再前往新的 您可以在自定义路由代码中定义此路由。

使用自定义组件进行路由时,您也可以向其中添加预提取功能。 如需在路由代码中实现预提取,请使用prefetch useRouter

我们来看看此示例应用中的 components/MyLink.js

预提取在 useEffect 钩子机制。如果 <MyLink> 上的 prefetch 属性设置为 true,即在 当呈现 <MyLink> 时,系统会预提取 href 属性:

useEffect(() => {
    if (prefetch) router.prefetch(href)
});

当您点击该链接时,路由在 handleClick 中完成。收到 记录到控制台,并且 push 方法会导航到新路由 在 href 中指定:

const handleClick = e => {
    e.preventDefault();
    console.log("Having fun with Next.js.");
    router.push(href);
};

在此示例应用中,index.js 页面包含一个指向 margherita.js<MyLink>pineapple-pizza.js。在 /margherita 上,prefetch 属性设置为 true 并前往 /pineapple-pizzafalse

<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza"  title="Pineapple pizza" prefetch={false} />

加载 index.js 时,Network 标签页会显示 margherita.js 已下载,但 pineapple-pizza.js 不是:

突出显示了 margherita.js 的开发者工具“网络”标签页。

当您点击任一链接时,控制台都会记录“ have fun with Next.js”。 然后导航到新路线:

开发者工具控制台显示“玩笑 Next.js”消息。

总结

当您使用 <Link> 时,Next.js 会自动预提取加载 呈现链接的网页,这样可以更快地导航到新网页。如果您 使用自定义路由,您可以使用 Next.js Router API 来实现 自动预提取。您可以停用 针对很少访问的网页进行预提取。