Next.js 如何通过路由预加载加快导航速度,以及如何对其进行自定义。
您将学到什么?
在本文中,您将了解 Next.js 中的路由的工作原理、如何针对速度进行优化,以及如何对其进行自定义以满足您的需求。
<Link>
组件
在 Next.js 中,您无需手动设置路由。Next.js 使用基于文件系统的路由,这样您只需在 ./pages/
目录中创建文件和文件夹即可:
如需链接到其他网页,请使用 <Link>
组件,方法与使用旧版 <a>
元素类似:
<Link href="/margherita">
<a>Margherita</a>
</Link>
当您使用 <Link>
组件进行导航时,Next.js 会为您执行更多操作。通常,当您点击指向网页的链接时,系统会下载该网页,但 Next.js 会自动预提取呈现该网页所需的 JavaScript。
当您加载包含多个链接的网页时,在您点击某个链接时,其背后的组件可能已经提取完毕。这样可以更快地导航到新页面,从而提高应用的响应速度。
在以下示例应用中,index.js
页面通过 <Link>
链接到 margherita.js
:
使用 Chrome 开发者工具验证 margherita.js
是否已预提取:
1. 如需预览网站,请按 View App(查看应用)。然后按 Fullscreen(全屏)。
- 按 `Control+Shift+J`(在 Mac 上为 `Command+Option+J`)打开 DevTools。
点击网络标签页。
选中停用缓存复选框。
重新加载页面。
加载 index.js
时,Network 标签页会显示 margherita.js
也已下载:
自动预提取的工作原理
Next.js 仅预加载视口中显示的链接,并使用 Intersection 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>
到 pineapple-pizza.js
的链接,其中 prefetch
设置为 false
:
如需检查网络活动,请按照第一个示例中的步骤操作。加载 index.js
时,开发者工具的 Network 标签页会显示 margherita.js
已下载,但未下载 pineapple-pizza.js
:
使用自定义路由进行预提取
<Link>
组件适用于大多数用例,但您也可以构建自己的组件来进行路由。Next.js 提供了 next/router
中的路由器 API,可让您轻松实现此目的。如果您想在导航到新路线之前执行某些操作(例如,提交表单),可以在自定义路由代码中定义该操作。
使用自定义组件进行路由时,您还可以为其添加预加载。如需在路由代码中实现预提取,请使用 useRouter
中的 prefetch
方法。
请查看以下示例应用中的 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
和 pineapple-pizza.js
的 <MyLink>
。对于 /margherita
,prefetch
属性设置为 true
;对于 /pineapple-pizza
,该属性设置为 false
。
<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza" title="Pineapple pizza" prefetch={false} />
加载 index.js
时,网络标签页会显示 margherita.js
已下载,而 pineapple-pizza.js
未下载:
当您点击任一链接时,控制台将记录“ has fun with Next.js.”并转到新路由:
总结
当您使用 <Link>
时,Next.js 会自动预提取呈现链接网页所需的 JavaScript,这样可以更快地导航到新网页。如果您使用的是自定义路由,则可以使用 Next.js 路由器 API 自行实现预加载。为不经常访问的网页停用预加载,以避免不必要地下载内容。