- Published on
使用 Next.js App Router 常犯的 10 个错误
- Authors
- Name
- cq
- Github
- @Jerryqun
前言
最近我看了 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/navigation
的useRouter
来取动态参数。
fetch
的 next: { revalidate }
控制缓存
4. 忘记使用 错误原因:服务端数据请求没有设置合理缓存策略,导致页面每次请求都重新渲染,性能下降。
避免方法:
- 在
fetch
请求中设置{ next: { revalidate: 秒数 } }
来开启 ISR(增量静态再生)。 - 明确缓存需求,合理设置缓存时间。
Link
组件或未优化路由跳转
5. 误用 错误原因:在 App Router 中混用旧版
next/link
或直接用<a>
标签跳转,丢失预加载、客户端导航等优势。
避免方法:
- 使用
next/link
(App Router 版本)进行导航。 - 避免直接使用原生
<a>
跳转 SPA 内路由。
'use client'
导致整体性能下降
6. 错误使用 错误原因:错误地给过大范围的文件加上
'use client'
,导致服务器组件变客户端组件,失去服务器渲染优势。
避免方法:
- 只给真正需要客户端特性的子组件添加
'use client'
。 - 保持最小化客户端组件范围。
7. 静态生成页面中直接访问数据库或环境变量而不注意安全
错误原因:不区分服务器组件和客户端组件,导致敏感数据(数据库连接、API Keys)错误暴露到浏览器。
避免方法:
- 数据库访问和环境变量只在服务器组件或 API Route 中使用。
- 客户端组件只接收服务器组件传递的数据。
8. 缺少错误边界(Error Boundary)和加载状态(Loading UI)
错误原因:没有为异步组件或动态页面设置错误捕获,用户体验不佳。
避免方法:
- 利用 App Router 提供的
error.tsx
和loading.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.tsx 和 loading.tsx 路由文件 |
静态与动态渲染混淆 | 区分静态生成与服务器渲染,合理使用 generateStaticParams |
布局嵌套混乱 | 规划清晰布局体系,熟悉嵌套路由继承规则 |