昨天最後提到,Next 有提供幾個「功能性路由」,可以在不影響 URL 的前提下,享受 Next 針對提升路由開發體驗的機制。今天來分享第一個情境:
有時候會因為協作需求,希望將幾個相同分類的 route segments 放進一個資料夾中,方便辨識。
舉例來說,我希望有個 /marketing
,用來放與行銷活動相關的 route segments,像是 /about
, /blog
等等:
app/
├─ marketing/
│ ├─ about/
│ │ ├─ page.tsx
│ ├─ blog/
│ │ ├─ page.tsx
但因為我們在 /about
和 /blog
父層加了一層 /marketing
,/about 的 URL path 會變成 /marketing/about;/blog URL path 會改為 /marketing/blog。
假如我希望使用相同的資料夾結構,但 marketing 不要是一個 route segment 該怎麼辦?
這時候可以使用其中一個功能性路由 - Route Groups!
顧名思義,Route Groups 能讓開發者在不影響 URL 的前提下分類路由,呼應 App Router 提升專案架構彈性的理念。
使用方法很簡單,我們只需要在用一個小括號 () 包住資料夾名稱。以上述例子來說,我們只要將 /marketing 改為 /(marketing)
,marketing 就不會被判斷為一個 route segment。
( 圖片來源:https://nextjs.org/docs/app/building-your-application/routing/route-groups )
除了透過路由分類,提升專案可維護性外,還有幾個常見的使用時機:
從 URL 結構來看,因為 marketing 不是一個 route segment,/about 和 /blog 應屬同階層,但我們一樣可以在 /(marketing) 中使用 layout.tsx
或 template.tsx
,來建立兩個路由共用的 layout。
比方說我們想讓 (/marketing) 中的 route segments 有個相同的 Header,就可以在 (/marketing) 中建一個 layout.tsx
import Header:
/* app/(marketing)/layout.tsx */
import Header from './components/Header';
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<Header />
{children}
</>
);
}
這樣當使用者進到 /about 和 /blog 都可以看到 <Header>
。
同理,我們也可以使用 loading.tsx
、error.tsx
來定義共用的 streaming UI 和 error boundaries UI。
因為只有在 route group 底下的 segments 才會吃到 route group 的 layout,而且 route group 不會影響到 URL,假如我們希望某個 route segment 底下 segment 不要套用 layout,也可以使用 route group 來達到效果。
舉例來說,我們希望 /dashboard 底下的 segments 可以有個相同的 Header,但唯獨 /dashboard/terms 不要有 Header,我們就可以將 layout.tsx
和需要 Header 的 segments 放進一個 route group 中,例如:
app/
├─ dashboard/
│ ├─ (withHeader)/
│ │ ├─ profile/
│ │ │ ├─ page.tsx
│ │ ├─ settings/
│ │ │ ├─ page.tsx
│ │ ├─ layout.tsx
│ ├─ terms/
│ │ ├─ page.tsx
這樣 /dashboard/profile 和 /dashboard/settings 會有 Header,但 /dashboard/terms 就不會有 Header。
所以我們也可以透過 route group 來讓 layout 使用起來更加彈性。
Day 09 有提到,我們可以透過 route group 讓 root layout 不止一個。
假設我們今天希望將第一層 route segments 分為 marketing 和 shop 兩個分類,並且讓這兩個分類的 UI 和 UX 完全不同,我們就可以在 /app 根目錄創建 (/marketing) 和 (/shop) 兩個 route group,並在個別的 layout.tsx
中建立 root layout,來設定個別的 metadata、字型、<head>
和 <body>
、全域共用的 components 等等。
( 圖片來源:https://nextjs.org/docs/app/building-your-application/routing/route-groups )
最後總結一下,幾個常見可以使用 route groups 的情境:
layout.tsx
、loading.tsx
、error.tsx
等特殊檔案Route groups 也可以用來解決其中一個功能性路由的 bug,這部分就留到明天分享。以上就是 route group 的介紹,明天會再跟大家分享兩個功能性路由!
謝謝大家耐心的閱讀,我們明天見!