实战指南:基于 with-prefetching 示例掌握默认、命令式与禁用三种预取模式)
Next.js 链接预取Prefetching实战指南基于 with-prefetching 示例掌握默认、命令式与禁用三种预取模式【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js本指南以当前仓库中的 with-prefetching 示例 为主体系统讲解 Next.js 路由预取Prefetching机制的三种典型用法Link默认的视口自动预取、通过router.prefetch()触发的命令式预取以及用prefetch{false}精确禁用预取。读完本文你将能在真实页面中按需组合这三种策略理解预取背后的源码触发条件并为页面/应用路由两种路由形态的导航体验做出合理的取舍。示例总览四种页面三种预取策略with-prefetching 是一个极简的 pages router 应用通过Nav导航组件把三种预取策略直观地演示在同一个导航栏里每种策略对应一到两个页面Home / Features走 Next.js 默认预取行为——只要Link出现在视口内viewport就自动在后台预取目标页面About命令式Imperative预取——通过prefetch{false}先关闭自动预取再借助router.prefetch(/about)在onMouseEnter等自定义时机手动拉取Contact完全禁用预取——Link prefetch{false}之后即使用户悬停也不发起预取。示例的导航组件源码位于 components/Nav.tsx四个页面pages/index.tsx、pages/features.tsx、pages/about.tsx、pages/contact.tsx都只是渲染标题占位用于在浏览器 Network 面板中直观对照有没有预取请求。页面本身通过 _app.tsx 统一挂载导航组件import type { AppProps } from next/app; import Nav from ../components/Nav; export default function App({ Component, pageProps }: AppProps) { return ( Nav / Component {...pageProps} / / ); }示例依赖非常精简见 package.jsonnext、react、react-dom配合dev/build/start三个标准脚本方便直接聚焦预取行为本身。模式一默认 API —— Link 进入视口即自动预取示例导航栏的默认策略对应下面这段 JSXLink href/Home/Link Link href/featuresFeatures/Link在默认配置下Next.js 的Link会自动对出现在视口内的链接发起预取。从 packages/next/src/client/link.tsx 的源码注释可以确认它的语义AnyLink /that is in the viewport (initially or through scroll) will be prefetched.任何处于视口内——无论是初始还是滚动进入——的Link /都会被预取。也就是说Home 与 Features 两个链接一旦出现在用户可视区域内浏览器就会在后台悄悄下载对应路由的产物与数据。等到用户真正点击跳转时目标页面资源已就绪导航因此显得瞬时完成。源码层确认预取触发的实际条件在 link.tsx 中组件会先根据 prop 计算预取开关const prefetchEnabled prefetchProp ! false随后通过useIntersection之类的可见性检测拿到isVisible并把可见与开关开启两个条件同时满足作为发起预取的前提见 link.tsx// If we dont need to prefetch the URL, dont do prefetch. if (!isVisible || !prefetchEnabled) { // ... } prefetch(router, href, as, { ... });其中prefetch内部会调用router.prefetch(href, as, options)见 link.tsx并对每个 URL 建立去重集合避免重复拉取同一目标见 link.tsx。预取请求即使失败也不会阻断后续真实导航——它本身只是提前做好功课的优化手段。值得注意的一个细节同一源码注释与逻辑也写明视口自动预取只在 production 构建下生效在开发模式下Link仅会在 hover 时预取以避免浪费资源开发时预取会触发页面即时编译见 link.tsx 附近注释。因此验证自动预取效果时应使用next build next start而非next dev。模式二命令式 API —— 在 onMouseEnter 等事件中手动预取自动预取对立刻可见的链接很理想但当预取成本较高或你希望把预取时机从进入视口改为用户即将点击等更精确的时刻时就需要命令式预取。示例中 About 链接的写法如下Link prefetch{false} href/about onMouseEnter{() { router.prefetch(/about); console.log(prefetching /about!); }} About /Link这里有两层关键设置prefetch{false}关闭自动预取先取消Link的默认行为避免同一目标被重复拉取onMouseEnter中调用router.prefetch(/about)鼠标刚进入链接区域即用户表现出导航意图时通过next/router的useRouter()拿到的router实例手动发起预取。这与 Next.js 官方建议的hover 即预取思路一致从鼠标移入链接到真正点击通常有几百毫秒的间隔恰好可以把预取时间藏进这段用户思考时间里。示例在回调里打印日志方便你在控制台直观看到命令式预取确实被触发了prefetching /about!命令式 API 的意义在于完全自定义触发时机。除了onMouseEnter还可以把它接到onFocus、onTouchStart、定时器、滚动阈值甚至某个业务事件上。凡是代码能拿到router实例的地方理论上都能主动调度一次预取。提示命令式预取的场景同样适合其他导航事件驱动型 UI。若你的导航是在自定义组件中实现而非使用Linkrouter.prefetch几乎是实现接近默认体验预取效果的标准手段。模式三禁用 API —— 用 prefetch{false} 精确关停并不是所有链接都值得预取。以下场景你可能希望彻底关掉预取目标页面路由的产物很大预取会挤占当前页所需带宽目标属于低频入口预取命中率低、得不偿失目标页面需要大量动态数据预取数据过期快价值有限。示例中 Contact 链接给出了最简写法Link prefetch{false} href/contact Contact /Link仅仅加一个prefetch{false}布尔属性即可。在 link.tsx 中它会使prefetchEnabled变为false进而让上文if (!isVisible || !prefetchEnabled)这条分支无论链接是否可见都直接短路——既不自动预取也不会在 hover 时预取。从 link.tsx 的文档注释还能看到在 app router 场景下prefetch属性还支持auto与true两种取值auto/null/undefined默认静态生成页面会预取完整的 React Server Component 数据动态页面则只预取到最近的带有loading.js的路由段避免拉取过多数据true无论是否存在loading.js分段都预取所有路由段的完整数据false任何情况下都不预取数据包括 hover。不过需要注意本示例本身跑在 pages router使用next/router的useRouterprefetch布尔开关与仅 production 生效的语义在两个路由形态下都成立而auto/true这类精细的数据粒度控制是 app routerLink的能力。选用哪种取值应以你项目实际采用的路由形态为准。如何运行与使用本示例本地引导使用create-next-app可以直接从示例模板初始化项目。仓库 README 提供三种主流包管理器对应的命令npx create-next-app --example with-prefetching with-prefetching-appyarn create next-app --example with-prefetching with-prefetching-apppnpm create next-app --example with-prefetching with-prefetching-app执行后会在当前目录生成with-prefetching-app应用。也可以直接在本仓库的examples/with-prefetching目录内安装并启动# 在 examples/with-prefetching 下 pnpm install pnpm dev # 开发模式 pnpm build # 生产构建 pnpm start # 运行生产服务器观察三种预取差异的验证步骤由于视口自动预取只在 production 生效建议按以下流程验证依次执行pnpm build与pnpm start打开首页打开浏览器开发者工具 Network 面板停留在首页不滚动、不悬停观察Home/Features链接对应的路由资源是否已在进入视口时被拉取默认 API将鼠标移入 About 链接但不点击观察控制台输出prefetching /about!且 Network 中出现/about资源命令式 API悬停或滚动到 Contact 链接确认始终没有针对/contact的预取请求禁用 API。云端部署示例的 README 也提供了标准的 Vercel 部署入口可通过create-next-app拉取后直接导入 Vercel 一键部署也可在 Vercel 控制台以该示例仓库为源创建新项目FRAMEWORK选择 Next.js 即可自动识别。部署形态与本地next start一致预取行为不会因运行环境不同而改变。生产实践建议结合示例与源码可以总结出几条落地准则把默认自动预取当默认项绝大多数站内导航都应保留默认行为让视口可见的链接自动预取换取最低成本的体验提升命令式预取用于有明确交互信号的入口自定义导航组件、需要比视口更早/更晚触发预取的场景使用router.prefetchprefetch{false}组合把触发时机收回到业务代码手中用禁用预取管理成本对超大体量或低命中率的目标路由显式prefetch{false}区分运行环境验证开发模式下只有 hover 才会预取务必在next build next start后的 production 环境中核对真实预取流量重复预取是无害且被去重的内部以 URL 维度维护去重集合见 link.tsx因此即便自动预取与命令式预取针对同一链接同时存在也不会产生双重请求。将本示例的Nav.tsx对照你项目中的导航组件逐条核对上面三种策略各自的命中场景即可系统性地把预取优化落到真实页面中。输出文章【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考