logo
Published on

使用 Next.js App Router 常犯的 10 个错误

Authors

前言

最近我看了 Vercel 的产品 VP Lee Robinson 的 Youtube 视频,作为一名前端开发工程师,他分享了很多 Next.js 相关的课程视频,其中就有一条他总结的《Next.js App Router 常犯的 10 个错误》的视频,我觉得非常有意义,所以记录下了这 10 个常犯错误的内容,从我自己的角度为大家介绍下这 10 个错误。

以下是使用 Next.js App Router(Next.js 13+ 新的文件系统路由方案)时常见的10个错误及避免方法,帮助你写出更健壮、高效的代码:


1. 误用或混用 Pages Router 与 App Router

错误原因:项目同时使用 app/ 目录(App Router)和 pages/ 目录(Pages Router),导致路由冲突或功能行为不一致。

避免方法:

  • 尽量专注使用一个路由系统(推荐 App Router)。
  • 如果必须混合使用,要明确混合规则和优先级,避免二者功能覆盖冲突。

2. 在服务器组件内误用客户端 API

错误原因:在默认的 React 服务器组件中使用只能在客户端运行的 Hook(如 useState, useEffect)或浏览器 API(如 window, document)。

避免方法:

  • 明确划分服务器组件和客户端组件。
  • 在需要用到客户端状态或效果的地方,用 'use client' 指令声明客户端组件。

3. 动态路由参数未正确类型声明

错误原因:在 app 目录下动态路由组件(如 [id]/page.tsx)的参数未正确通过函数参数获取,或误用 useRouter 去读参数。

避免方法:

  • App Router 下动态路由参数通过 props.params 传入或通过 generateStaticParams 进行静态路径预渲染。
  • 不要用 next/navigationuseRouter 来取动态参数。

4. 忘记使用 fetchnext: { revalidate } 控制缓存

错误原因:服务端数据请求没有设置合理缓存策略,导致页面每次请求都重新渲染,性能下降。

避免方法:

  • fetch 请求中设置 { next: { revalidate: 秒数 } } 来开启 ISR(增量静态再生)。
  • 明确缓存需求,合理设置缓存时间。

错误原因:在 App Router 中混用旧版 next/link 或直接用 <a> 标签跳转,丢失预加载、客户端导航等优势。

避免方法:

  • 使用 next/link(App Router 版本)进行导航。
  • 避免直接使用原生 <a> 跳转 SPA 内路由。

6. 错误使用 'use client' 导致整体性能下降

错误原因:错误地给过大范围的文件加上 'use client',导致服务器组件变客户端组件,失去服务器渲染优势。

避免方法:

  • 只给真正需要客户端特性的子组件添加 'use client'
  • 保持最小化客户端组件范围。

7. 静态生成页面中直接访问数据库或环境变量而不注意安全

错误原因:不区分服务器组件和客户端组件,导致敏感数据(数据库连接、API Keys)错误暴露到浏览器。

避免方法:

  • 数据库访问和环境变量只在服务器组件或 API Route 中使用。
  • 客户端组件只接收服务器组件传递的数据。

8. 缺少错误边界(Error Boundary)和加载状态(Loading UI)

错误原因:没有为异步组件或动态页面设置错误捕获,用户体验不佳。

避免方法:

  • 利用 App Router 提供的 error.tsxloading.tsx 路由文件进行错误处理和加载指示。
  • 在必要的地方自定义错误边界。

9. 混淆静态渲染和服务器渲染的区别

错误原因:误以为所有页面自动静态生成,忽视了动态数据更新的需求,导致页面内容过时。

避免方法:

  • 明确使用动态渲染(动态参数编写)、增量静态再生 revalidate
  • 使用 generateStaticParams 明确静态路径。

10. 布局文件和嵌套路由结构不清晰

错误原因:layout.tsx 文件放置位置和作用域混乱,导致页面复用和样式继承异常。

避免方法:

  • 充分运用嵌套路由的布局,合理拆分布局文件。
  • 理解父子布局的继承和嵌套关系,避免无用或冗余布局。

总结

常见错误避免方法
混用 Pages Router 和 App Router专注一个路由体系,避免冲突
服务器组件中误用客户端 API'use client' 划分客户端组件
动态路由参数处理错误通过 props.params 获取参数,避免用 useRouter
忽略缓存配置fetch 加入 { next: { revalidate: x } } 进行缓存控制
路由跳转未用 next/link统一使用 Next.js Link 组件
'use client' 滥用仅客户端必要范围添加,保持大部分为服务器组件
敏感信息暴露服务器组件处理数据,前端接收干净数据
缺错误边界和加载态使用 error.tsxloading.tsx 路由文件
静态与动态渲染混淆区分静态生成与服务器渲染,合理使用 generateStaticParams
布局嵌套混乱规划清晰布局体系,熟悉嵌套路由继承规则