結論
Next.js 15 では、Server Components の layout と page は並列に実行されるため、明確な親子の実行順序は保証されません。一方で、Client Components に関しては従来通り、親 → 子の順序で実行される挙動を維持しています。
検証の背景
Next.js 15 でlayoutの実行順序がpageよりも早くなったと耳にしていたのですが、実際にどういう挙動になっているのかを確認してみたかったので検証してみました。
検証に使用したリポジトリはこちら
👉 https://github.com/hrfm1623/test-next15-rendering-order
検証環境
- Next.js 15
- TypeScript
- React
検証項目
- デフォルトのレンダリング順序
- Client Components(Layout/Page)の実行順序
- Client Layout で null を返すケース
- RSC Page でエラーが発生するケース
検証結果
1. デフォルトのレンダリング順序(Server Components)
実際のログ:
🔵 [Middleware] Start Processing /blog/server
🟢 [RootLayout] Start Root Layout Rendering
🟡 [BlogLayout] Start Blog Layout Rendering
🟡 [ServerBlogLayout] Start Server Blog Layout Rendering
🟡 [ServerBlogPage] Start Server Blog Page Rendering
🟡 [BlogLayout] Async Operation Complete
🟡 [ServerBlogLayout] Async Operation Complete
🟢 [RootLayout] Async Operation Complete
🟢 [ServerComponent] Start Server Component Rendering
🔴 [ClientComponent] Initial Client Component Render
🟡 [ServerBlogPage] Async Operation Complete
🟢 [ServerComponent] Async Operation Complete
- 基本的にlayout → page の順に実行開始され、layoutのレンダリングを待たずにpageのレンダリングが始まる
2. Client Components(Layout/Page)の実行順序
実際のログ:
🔵 [Middleware] Start Processing /blog/client
🟢 [RootLayout] Start Root Layout Rendering
🟡 [BlogLayout] Start Blog Layout Rendering
🟡 [BlogLayout] Async Operation Complete
🟢 [RootLayout] Async Operation Complete
🟢 [ServerComponent] Start Server Component Rendering
🔴 [ClientComponent] Initial Client Component Render
🔴 [ClientBlogLayout] Initial Client Blog Layout Render
🔴 [ClientBlogPage] Initial Client Blog Page Render
🟢 [ServerComponent] Async Operation Complete
- Client Components はComponent → Layout → Page
3. Client Layout で null を返すケース
実際のログ:
🔵 [Middleware] Start Processing /null-client
🟢 [RootLayout] Start Root Layout Rendering
🟡 [NullClientPage] Start Page Rendering
🟢 [RootLayout] Async Operation Complete
🟡 [NullClientPage] Async Operation Complete
🟢 [ServerComponent] Start Server Component Rendering
🔴 [ClientComponent] Initial Client Component Render
🔴 [NullClientLayout] Initial Client Layout Render
🔴 [NullClientLayout] Returning null
🟢 [ServerComponent] Async Operation Complete
- Server Components の実行は通常通り完了
- Client Layout が null を返してもエラーにならない
- Page コンテンツは表示されない
4. RSC Page でエラーが発生するケース
実際のログ:
🔵 [Middleware] Start Processing /error-page
🟢 [RootLayout] Start Root Layout Rendering
🟡 [ErrorLayout] Start Layout Rendering
🟡 [ErrorPage] Start Page Rendering
🟡 [ErrorPage] Before Error
⨯ Error: Intentional RSC Page Error
at ErrorPage (src/app/error-page/page.tsx:8:8)
6 |
7 | // 意図的にエラーを発生させる
> 8 | throw new Error("Intentional RSC Page Error");
| ^
9 |
10 | return (
11 | <div className="p-4"> {
digest: '53399773'
}
🟡 [ErrorLayout] Async Operation Complete
🟢 [RootLayout] Async Operation Complete
🟢 [ServerComponent] Start Server Component Rendering
🔴 [ClientComponent] Initial Client Component Render
🟢 [ServerComponent] Async Operation Complete
- エラーが発生したコンポーネント以外は実行継続
まとめ
- Server Components: layoutから実行開始されるが、layoutのレンダリングを待たずにpageのレンダリングが始まるため実行順序の保証はできない
- Client Components: 従来通りの親子順序を維持