Layouts RFC
投稿者: Delba de Oliveira (@delba_oliveira)、Lee Robinson (@leerob)、Sebastian Markbåge (@sebmarkbage)、Tim Neutkens (@timneutkens)
このRFC(Request for Comment)は、2016年にNext.jsが導入されて以来最大のアップデートについて概説します:
- ネストされたレイアウト: ネストされたルートを持つ複雑なアプリケーションを構築
- Server Components向けに設計: サブツリーナビゲーション用に最適化
- 改善されたデータフェッチング: ウォーターフォールを回避しながらレイアウト内でフェッチ
- React 18機能の使用: Streaming、Transitions、Suspense
- クライアントとサーバールーティング: SPA的な動作を持つサーバー中心のルーティング
- 100%段階的に採用可能: 破壊的変更がないため段階的に採用可能
- 高度なルーティングパターン: 並列ルート、インターセプトルートなど
新しいNext.jsルーターは、最近リリースされたReact 18機能の上に構築されます。これらの新機能を簡単に採用し、それらが提供する利点を活用できるデフォルトと規約を導入する予定です。
このRFCの作業は進行中であり、新機能が利用可能になったときに発表します。フィードバックを提供するには、GitHub Discussionsでの議論に参加してください。
目次
- Motivation
- Terminology
- How Routing Currently Works
- The app Directory
- Defining Routes
- Layouts
- Pages
- React Server Components
- Data Fetching
- Route Groups (New)
- Server Centric Routing (New)
- Instant Loading States (New)
- Error Handling (New)
- Templates (New)
- Advanced Routing Patterns (New)
- Conclusion
モチベーション
GitHub、Discord、Reddit、開発者調査からNext.jsのルーティングの現在の制限についてコミュニティフィードバックを収集してきました。以下のことがわかりました:
- レイアウト作成の開発者体験は改善できる。ネスト可能で、ルート間で共有でき、ナビゲーション時に状態が保持されるレイアウトを簡単に作成できるべき。
- 多くのNext.jsアプリケーションはダッシュボードやコンソールであり、より高度なルーティングソリューションの恩恵を受ける。
現在のルーティングシステムはNext.jsの開始以来うまく機能していますが、開発者がより高性能で機能豊富なWebアプリケーションを構築しやすくしたいと考えています。
フレームワークメンテナーとして、後方互換性があり、Reactの未来と整合するルーティングシステムを構築したいと考えています。
注意: 一部のルーティング規約は、Server Componentsの機能の一部が元々開発されたMetaのRelayベースルーター、およびReact RouterやEmber.jsなどのクライアントサイドルーターからインスピレーションを得ています。layout.jsファイル規約はSvelteKitで行われた作業からインスピレーションを得ています。
用語
このRFCは新しいルーティング規約と構文を導入します。用語はReactと標準的なWebプラットフォーム用語に基づいています。
- Tree: 階層構造を視覚化するための規約。例:親と子コンポーネントを持つコンポーネントツリー、フォルダ構造など
- Subtree: ツリーの一部で、ルート(最初)から始まりリーフ(最後)で終わる
- URL Path: ドメインの後に来るURLの部分
- URL Segment: スラッシュで区切られたURLパスの部分
現在のルーティングの仕組み
現在、Next.jsはファイルシステムを使用して、Pagesディレクトリ内の個々のフォルダとファイルをURL経由でアクセス可能なルートにマッピングします。各ページファイルはReact Componentをエクスポートし、ファイル名に基づいた関連ルートを持ちます。
Dynamic Routes: Next.jsは[param].js、[...param].js、[[...param]].js規約でDynamic Routes(catch allバリエーションを含む)をサポートします。
Layouts: Next.jsは、シンプルなコンポーネントベースレイアウト、コンポーネントプロパティパターンを使用したページごとのレイアウト、カスタムappを使用した単一のグローバルレイアウトをサポートします。
Data Fetching: Next.jsはページ(ルート)レベルで使用できるデータフェッチングメソッド(getStaticProps、getServerSideProps)を提供します。
Rendering: Next.jsは3つのレンダリングオプションを提供します:Static Generation、Server-Side Rendering、Client-Side Rendering。
appディレクトリの導入
これらの新しい改善を段階的に採用でき、破壊的変更を回避するために、appという新しいディレクトリを提案します。
appディレクトリはpagesディレクトリと並行して動作します。アプリケーションの一部を新しいappディレクトリに段階的に移動して、新機能を活用できます。
後方互換性のため、pagesディレクトリの動作は同じままで、引き続きサポートされます。
ルートの定義
app内のフォルダ階層を使用してルートを定義できます。ルートは、ルートフォルダから最終的なリーフフォルダまでの階層に従った、ネストされたフォルダの単一パスです。
例えば、appディレクトリに2つの新しいフォルダをネストすることで、新しい/dashboard/settingsルートを追加できます。
注意: このシステムでは、フォルダを使用してルートを定義し、ファイルを使用してUI(layout.js、page.js、RFCの第2部のloading.jsなどの新しいファイル規約)を定義します。
ルートセグメント
サブツリー内の各フォルダはルートセグメントを表します。各ルートセグメントは、URLパス内の対応するセグメントにマッピングされます。
例えば、/dashboard/settingsルートは3つのセグメントで構成されます:
/ルートセグメント
dashboardセグメント
settingsセグメント
Layouts
新しいファイル規約: layout.js
レイアウトは、サブツリー内のルートセグメント間で共有されるUIです。レイアウトはURLパスに影響せず、ユーザーが兄弟セグメント間をナビゲートするときに再レンダリングされません(React stateが保持されます)。
レイアウトは、layout.jsファイルからReact componentをデフォルトエクスポートすることで定義できます。コンポーネントは、レイアウトがラップするセグメントで埋められるchildren propを受け入れる必要があります。
2種類のレイアウトがあります:
- Root layout: すべてのルートに適用
- Regular layout: 特定のルートに適用
Root Layout
appフォルダ内にlayout.jsファイルを追加することで、アプリケーションのすべてのルートに適用されるroot layoutを作成できます。
注意: root layoutは、すべてのルートに適用されるため、カスタムApp(_app.js)とカスタムDocument(_document.js)の必要性を置き換えます。
Regular Layouts
特定のフォルダ内にlayout.jsファイルを追加することで、アプリケーションの一部にのみ適用されるレイアウトを作成することもできます。
ネストされたレイアウト
レイアウトはデフォルトでネストされます。例えば、上記の2つのレイアウトを組み合わせる場合、root layout(app/layout.js)がdashboard layoutに適用され、これもdashboard/*内のすべてのルートセグメントに適用されます。
Pages
新しいファイル規約: page.js
ページは、ルートセグメントに固有のUIです。フォルダ内にpage.jsファイルを追加することでページを作成できます。
ユーザーが/dashboard/settingsを訪問すると、Next.jsはsettingsフォルダのpage.jsファイルを、サブツリーのさらに上に存在するレイアウトでラップしてレンダリングします。
レイアウトとページの動作
- ファイル拡張子
js|jsx|ts|tsxをPagesとLayoutsに使用できます
- Page Componentsは
page.jsのデフォルトエクスポートです
- Layout Componentsは
layout.jsのデフォルトエクスポートです
- Layout Componentsは
children propを受け入れる必要があります
例
export default function RootLayout({ children }) {
return (
<html>
<body>
<Header />
{children}
<Footer />
</body>
</html>
);
}
export default function DashboardLayout({ children }) {
return (
<>
<DashboardSidebar />
{children}
</>
);
}
export default function AnalyticsPage() {
return <main>...</main>;
}
上記のレイアウトとページの組み合わせは、以下のコンポーネント階層をレンダリングします:
<RootLayout>
<Header />
<DashboardLayout>
<DashboardSidebar />
<AnalyticsPage>
<main>...</main>
</AnalyticsPage>
</DashboardLayout>
<Footer />
</RootLayout>
React Server Components
注意: Reactは新しいコンポーネントタイプを導入しました:Server、Client(従来のReactコンポーネント)、Shared。これらの新しいタイプについて詳しく学ぶには、React Server Components RFCを読むことをお勧めします。
このRFCにより、React機能の使用を開始し、React Server ComponentsをNext.jsアプリケーションに段階的に採用できます。新しいルーティングシステムの内部は、Streaming、Suspense、TransitionsなどのReact機能も活用します。
デフォルトとしてのServer Components
pagesとappディレクトリ間の最大の変更の1つは、デフォルトでapp内のファイルがReact Server Componentsとしてサーバーでレンダリングされることです。
これにより、pagesからappに移行する際にReact Server Componentsを自動的に採用できます。
注意: Server componentsはappフォルダまたは独自のフォルダで使用できますが、後方互換性のためpagesディレクトリでは使用できません。
Client and Server Components規約
appフォルダはserver、client、sharedコンポーネントをサポートし、これらのコンポーネントをツリー内でインターリーブできます。
Client ComponentsとServer Componentsを定義する正確な規約については継続的な議論があります。この議論の解決に従います。
現在のところ:
- Server componentsはファイル名に
.server.jsを追加して定義できます(例:layout.server.js)
- Client componentsはファイル名に
.client.jsを追加して定義できます(例:page.client.js)
.jsファイルはshared componentsと見なされます
注意: ClientとServer componentsには尊重すべき制約があります。clientまたはserver componentの使用を決定する際は、server