---
# System prepended metadata

title: 'Next.js App Router: 利用 Route Groups (群組路徑) 打造獨立頁面的多重 Layout 架構'
tags: [next.js]

---

# Next.js App Router: 利用 Route Groups (群組路徑) 打造獨立頁面的多重 Layout 架構

在最一開始接觸 Next.js App Router 時，通常我們會有一個根目錄下的 `app/layout.tsx` 作為全站共用的佈局 (像是 Navbar 或 Footer)

但筆者在開發中，剛好遇到這樣的需求：「登入頁面」為一個完全獨立、沒有側邊欄的乾淨頁面，或者「後臺管理頁面」需要專屬的 Navbar。
這時候，Next.js 的 Route Group (群組路徑) 功能就是最佳解法。這篇文章將分享如何利用 Route Groups 來實現「不影響 URL 結構」的前提下，為不同頁面群組套用完全獨立的 Layout。

## 什麼是 Route Groups

在 `app` 目錄下，如果將資料夾名稱用括號 `()` 包起來，例如 `(admin)` 或 `(marketing)`，Next.js 就會將其視為 Route Group

![image](https://hackmd.io/_uploads/rks7IUBW-g.png)

以下是 Route Group 的特點：
1. 不影響 URL 路徑：`(marketing)/about` 的網址依然是`/about`，括號內的名稱不會出現在網址當中
2. 可以擁有獨立的 Layout

## 實作場景範例

假設我們的網站有兩個主要區塊，且它們的 UI 結構完全不同：
1. 行銷網站 (Marketing)：需要由 Header、Hero Section、Footer 組成
2. 後臺儀表板 (Dashboard)：需要側邊欄 (Sidebar) 和頂部功能列，且不需要官網的 Footer

如果不使用 Route Groups，我們很難在同一個 `app/layout.tsx` 中完美切割這兩種結構

### 檔案結構規劃

我們可以修改 `app/layout.tsx` 讓它只保留 HTML/body 元素，然後建立兩個 Route Groups：

```bash
app/
├── (marketing)/      # 官網群組
│   ├── layout.tsx    # 官網專用的 Layout (含 Navbar, Footer)
│   ├── page.tsx      # 對應路由：/
│   └── about/
│       └── page.tsx  # 對應路由：/about
│
├── (dashboard)/      # 後台群組
│   ├── layout.tsx    # 後台專用的 Layout (含 Sidebar)
│   └── dashboard/
│       └── page.tsx  # 對應路由：/dashboard
├── layout.tsx # 根 layout，放置基礎的 HTML/body
└── favicon.ico
```

### 程式碼範例

#### 根目錄的 Layout `app/layout.tsx`

```typescript
export default function Layout({ children }) {
    return (
        <html lang="zh-TW">
            <body>
                {children}
            </body>
        </html>
    )
}
```

#### 行銷網站 Layout `app/(marketing)/layout.tsx`

```typescript
export default function MarketingLayout({
    children
}: { 
    children: React.ReactNode 
}) {
    return (
        <>
            <nav>導航列</nav>
            <main>{children}</main>
            <footer>頁尾</footer>
        </>
    )
}
```

#### 後臺儀表板 Layout `app/(dashboard)/layout.tsx`

```typescript
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="flex">
        <aside>後台側邊欄</aside>
        <div className="flex-1">
            <header>後台頂部功能列</header>
            <main className="p-4">{children}</main>
        </div>
    </div>
  )
}
```

:::info
除了修改 `app/layout.tsx` 保留基礎 HTML/body，你也可以選擇直接刪除 `app/layout.tsx`，在各 Route Groups 中都建立 `layout.tsx`，不過當你使用此方法時，所有的 `layout.tsx` 都必須包含 `<html>` 和 `<body>` 標籤唷
:::


## 參考資料

- [File-system conventions: Route Groups | Next.js](https://nextjs.org/docs/app/api-reference/file-conventions/route-groups)