You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS 13 App Router路由与目录结构最佳实践咨询

Next.js App Router 路由与结构实战指南

一、核心逻辑先搞懂

App Router 核心就是文件即路由:app 目录下的文件夹对应 URL 路径,每个文件夹里的 page.js 就是该路径的页面。带括号的文件夹(比如 (auth))是路由分组,只做逻辑归类,不会出现在最终 URL 里。

二、整体目录结构示例

直接上最实用的结构,对应登录注册、仪表盘、首页等常见场景:

app/
├── (auth)/          # 身份验证页面分组(URL 不会带 (auth))
│   ├── layout.js    # 登录注册专属极简布局(比如无导航栏)
│   ├── login/
│   │   ├── components/
│   │   │   └── LoginForm.jsx
│   │   └── page.js  # 对应 URL: /login
│   └── register/
│       ├── components/
│       │   └── RegisterForm.jsx
│       └── page.js  # 对应 URL: /register
├── (dashboard)/     # 登录后专属区域分组
│   ├── layout.js    # 仪表盘布局(侧边栏+顶部导航)
│   ├── home/
│   │   └── page.js  # 对应 URL: /home
│   └── settings/
│       └── page.js  # 对应 URL: /settings
├── layout.js        # 全局根布局(所有页面共享的基础结构)
├── page.js          # 首页(URL: /)
└── not-found.js     # 404 页面

为什么这么分?

  • (auth) 分组:把登录、注册这类独立页面归在一起,它们不需要和仪表盘共享布局,单独做极简布局更合理。
  • (dashboard) 分组:集中管理登录后才能访问的页面,方便统一加权限验证(比如在该分组的 layout.js 里写登录校验逻辑)。

三、登录/注册页面的放置细节

  1. 路径对应:app/(auth)/login/page.js 直接对应 /login,用户访问这个 URL 就会加载该页面。
  2. 专属布局:给 (auth) 加个 layout.js,让登录注册页面用干净的布局,比如:
// app/(auth)/layout.js
export default function AuthLayout({ children }) {
  // 这里只返回必要的容器,去掉全局导航栏
  return <div className="min-h-screen bg-gray-50">{children}</div>;
}

这样登录页面就不会显示全局的头部导航,更符合用户体验。

四、组件存放与分组方法

组件分两类存放,别乱堆:

1. 页面专属组件

只给某个页面用的组件,直接放在该页面的文件夹下,比如登录页面的 LoginForm:

app/(auth)/login/
├── components/
│   └── LoginForm.jsx
└── page.js

好处:找组件的时候直接去对应页面文件夹里找,不用全局搜。

2. 全局共享组件

多个页面都会用到的组件(比如按钮、输入框、导航栏),放在项目根目录的 components/ 下,按功能分组:

components/
├── UI/              # 基础UI组件(按钮、输入框、卡片)
│   ├── Button.jsx
│   ├── Input.jsx
│   └── Card.jsx
├── Layout/          # 布局组件(全局头部、仪表盘侧边栏)
│   ├── Header.jsx
│   └── Sidebar.jsx
└── Auth/            # 身份验证相关共享组件(比如验证码输入框)
    └── CaptchaInput.jsx

使用的时候用绝对路径导入(需要在 jsconfig.json 里配置 baseUrl: "."):

// 导入全局UI组件
import Button from '@/components/UI/Button';

五、实用代码示例

登录页面代码

// app/(auth)/login/page.js
import LoginForm from './components/LoginForm';

export default function LoginPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <LoginForm />
    </div>
  );
}

登录表单组件

// app/(auth)/login/components/LoginForm.jsx
import Input from '@/components/UI/Input';
import Button from '@/components/UI/Button';

export default function LoginForm() {
  return (
    <div className="w-full max-w-md bg-white p-6 rounded-lg shadow-md">
      <h2 className="text-2xl font-bold mb-6 text-center">登录账号</h2>
      <form>
        <Input label="邮箱" type="email" placeholder="请输入邮箱" className="mb-4" />
        <Input label="密码" type="password" placeholder="请输入密码" className="mb-6" />
        <Button type="submit" className="w-full bg-blue-600 hover:bg-blue-700 text-white">
          登录
        </Button>
      </form>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Dead

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:25:23