Next.js嵌套路由失效?详解page.tsx命名规范与动态路由结构
Next.js App Router要求所有路由页面必须以page.tsx(或.jsx)命名并置于对应文件夹内,直接在动态段路径下创建login.tsx等非标准文件名无法触发路由匹配。 你是否遇到过这样的困惑:在Next.js的App Router中,明明按照直觉创建了/app/[locale]/a

Next.js App Router要求所有路由页面必须以page.tsx(或.jsx)命名并置于对应文件夹内,直接在动态段路径下创建login.tsx等非标准文件名无法触发路由匹配。
你是否遇到过这样的困惑:在Next.js的App Router中,明明按照直觉创建了/app/[locale]/admin/login.tsx文件,却始终无法通过/admin/login这个URL访问到它?页面不是404就是渲染错误。
问题的根源其实很明确:Next.js App Router的路由机制完全由文件系统的“结构”决定,而不是由文件的“名字”决定。简单来说,框架只认特定命名的“路由段文件”,你随意创建一个.tsx文件,它并不会被自动注册为路由。
正确的路由约定(App Router 核心规则)
想要一个URL路径能够被访问,关键在于必须存在一个包含page.tsx文件的文件夹。这个文件夹的名字就是URL中的路径段,而文件夹里的page.tsx就是该路径默认渲染的组件。
| 文件路径 | 对应 URL | 是否有效 | 说明 |
|---|---|---|---|
| /app/[locale]/admin/page.tsx | /admin | admin 是文件夹,page.tsx 定义其内容 | |
| /app/[locale]/admin/login/page.tsx | /admin/login | login 是子文件夹,符合嵌套结构 | |
| /app/[locale]/admin/login.tsx | 无匹配路由 | login.tsx 是平级文件,不构成路由段,Next.js 忽略 |
所以,/app/[locale]/admin/login.tsx这个文件,在Next.js眼里,和一个普通的工具文件(比如utils/helper.ts)没什么区别,它根本不会为这个文件创建任何路由。这也就解释了为什么/admin/login路径会失效。
解决方案:保持语义化并遵守约定
解决之道并非妥协于“目录嵌套太深”,而是通过合理组织文件夹层级并坚持语义化命名,来同时满足代码清晰性和框架规范性。正确的结构应该是这样的:
/app/
└── [locale]/
└── admin/
├── page.tsx # → /admin
└── login/
└── page.tsx # → /admin/login 标准且可读
这样一来,/app/[locale]/admin/login/page.tsx文件的内容就可以专注于业务逻辑了:
// /app/[locale]/admin/login/page.tsx
import '../globals.scss';
export default function LoginPage() {
return (
Admin Login
{/* 登录表单逻辑 */}
);
}
提示:顶层的
[locale]是一个动态路由段,但这并不影响其内部子路径的规则。只要/admin/login/这个文件夹里存在page.tsx,该路由就会生效,与[locale]具体是“en”还是“zh”无关。
常见误区与注意事项
为了避免再次踩坑,有几个关键点需要牢记:
- 不要重命名 page.tsx:诸如
login.tsx、index.tsx或default.tsx等文件名都是无效的,只有page.tsx(或page.jsx)才会被识别为路由入口。 layout.tsx和loading.tsx是可选辅助文件,它们用于定义布局和加载状态,但一个可访问的路由终点必须有page.tsx。- 如果你的路由需要支持嵌套,比如
/admin/login和/admin/login/forgot,那么文件夹结构应该如下:/admin/login/ ├── page.tsx # /admin/login └── forgot/ └── page.tsx # /admin/login/forgot - 动态路由段(如
[id]、[locale])可以和普通文件夹自由组合,但无论如何组合,每一层路由的终点都必须是一个包含page.tsx的文件夹。
总结
归根结底,Next.js App Router的设计哲学可以概括为“文件即路由,文件夹即路径”。放弃追求“扁平化文件名”的旧习惯,转而拥抱语义化的文件夹结构(例如使用login/文件夹而非login.tsx文件),这不仅仅是遵循框架设计,更能显著提升项目的可维护性。
试想,/admin/login/page.tsx这种结构,是不是比一个孤零零的admin-login.tsx文件更能清晰地表达页面层级关系?而且,这种结构也为未来的功能扩展(比如新增一个login/error/page.tsx)铺平了道路。严格遵守page.tsx的命名规范,无疑是解锁Next.js强大路由能力的第一把,也是最重要的一把钥匙。
