Next.jsでのレンダリング方式について 〜〜知らない単語が多くて、ちょっと何言ってるのかわからない〜〜

よくわからないことは生成AIに聞いてみよう！

Q. Next.jsを調べていて、プリレンダリングとかハイドレーションといった単語があってよくわからないので、このあたり解説してもらえますか？
↓
![FireShot Capture 002 - Claude - claude.ai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338282/2298d6a1-1c52-aa5f-72c2-2e2e330677ca.png)


![わからない.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338282/2da0a0f7-01b3-b6f8-9eed-6f95327d017f.jpeg)

## はじめに
本記事は会社勉強会での発表のための資料となります。
あと最近は業務でもNext.jsに携わることが増えてきたので、ちゃんと理解して使えるようになっておかねばという焦りなんかもあったりなかったり。

トピックとしてはキャッシュ周り、Server Actionsか、レンダリング方式かあたりのどれかをまとめようと思いましたが、~~レンダリング以外は難しそうだしまとめきれなさそうだったので~~レンダリングの理解不足により、ビルドしたあとに予期せぬエラーが発生したりしたので、CSRやSSRといったレンダリングについて改めてまとめてみます。

## 対象のバージョン
Next.js 14.x
React 18.x

## 本記事の目標
大体以下のようなことが達成できれば◎
- そもそもいろいろなレンダリング手法がある背景、歴史について理解できる
- 各レンダリング方式について大枠が理解できる
- RSC(React Server Component)を抑えることができる
    - RSCを知ることで、Next.jsがApp Router方式を採用する背景に何があったのかが理解できる
- Reactの文脈のクライアントコンポーネント、サーバーコンポーネントの違い

## ReactとNext.jsの歴史
簡単に図にまとめると以下のような感じになります。
![FireShot Capture 001 - Claude - claude.ai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338282/70c23b24-7351-65a7-a43b-b69a4da3ec4a.png)

0. （図にはないが）React登場以前、いわゆるシンプルなMPA時代
1. 2013年 Reactがリリース（CSR：クライアントサイドレンダリング）
2. 2016年 Next.jsがリリース（SSR：サーバーサイドレンダリング）
3. 2020年 React Server Component(RSC)の登場
4. 2023年 Next.js13.4でApp Routerが安定版リリース

このあたりの歴史の流れについては、以下の記事で詳細に記載されています。
[Next.jsから学ぶWebレンダリング ~React誕生以前からApp Router with RSCまでの流れ~](https://zenn.dev/suzu_4/articles/2e6dbb25c12ee5)

### 2013年
まずReactが登場したことによってCSRという概念が一般的なものとなりました。
それ以前からBackbone.jsやAngularなどによるSPAアプリケーション自体はすでに存在していましたが、やはり普及に最も影響力があったのはこのタイミングな気がします。

### 2016年
その後、CSRの課題である初期表示の遅さやSEO課題などが指摘されるようになり、それらを解決するために登場してきたのが、Next.jsやNuxt.jsといったSSRが可能なフレームワークです。

### 2020年
React Server Componentと呼ばれる新たな仕組みが登場しました。
RSCについては後述。

### 2023年
Next.js側でRSCを利用できるようなアーキテクチャに寄せるべく、AppRouterと呼ばれるルーティングシステムが登場しました。
大きな変更点が多々ありますが、今回の記事としてはやはり、デフォルトのレンダリングがCSRからSSRに変更になったという点でしょうか。

## CSR、SSR、SSG
### CSR クライアントサイドレンダリング
```mermaid
sequenceDiagram
    actor User as ユーザー
    participant Browser as クライアント（ブラウザ）
    participant Server as サーバー
    
    User->>Browser: URLにアクセス
    Browser->>Server: ページリクエスト
    Server-->>Browser: 最小限のHTML + JavaScript
    Browser->>Browser: JavaScriptを実行
    Browser->>Browser: Reactコンポーネントをレンダリング
    Browser-->>User: 完全なページを表示
    User->>Browser: ユーザーの操作
    Browser->>Browser: 状態更新(useStateとかが発火する)
    Browser-->>User: 即時UI更新
    Browser->>Server: 必要に応じてデータフェッチ
    Server-->>Browser: JSONデータ
    Browser->>Browser: 新データでUI更新
    Browser-->>User: 更新されたUI表示
```
後述するSSRやSSG含め、個人的には一番シンプルなレンダリング手法かと思います。
クライアントからの要求を受取、最低限のHTML
```html
<div id="root"></div>
```
のようなDOMとJavaScriptを返します。

### SSR サーバーサイドレンダリング
```mermaid
sequenceDiagram
    actor User as ユーザー
    participant Browser as クライアント（ブラウザ）
    participant Server as サーバー
    participant DB as データベース/API

    User->>Browser: URLにアクセス
    Browser->>Server: ページリクエスト
    Server->>DB: データフェッチ
    DB-->>Server: データ返却
    Server->>Server: Reactコンポーネントをレンダリング
    Server-->>Browser: 完全なHTML + JavaScript
    Browser-->>User: 完全なページを表示
    Browser->>Browser: JavaScriptを実行（ハイドレーション）
    User->>Browser: ユーザーの操作
    alt クライアントサイド更新
        Browser->>Browser: 状態更新(useStateとかが発火する)
        Browser-->>User: 即時UI更新
    else サーバーサイド更新
        Browser->>Server: 新しいページ/データリクエスト
        Server->>DB: 追加データフェッチ
        DB-->>Server: データ返却
        Server->>Server: 新しいHTMLを生成
        Server-->>Browser: 更新されたHTML
        Browser-->>User: 更新されたページを表示
    end
```
初期表示が大きく変わり、今度はサーバー側で「完全なHTML + JavaScript」を生成して、それをブラウザに返却するようになりました。

さて、SSRの文脈を追うことで、記事の最初に出てきていた「ハイドレーション」というキーワードが出てきました。
ハイドレーションとは何なのでしょうか。

#### ハイドレーションとプリレンダリング
ハイドレーションとは日本語でいうと「水分補給」という意味です。
webフロントエンドの文脈から見ると
「まだ動きがついていない、乾いた状態のHTMLにJavaScript（水分）を注入することで動きのある状態に変化させること」
といった意味での解釈が妥当になりそうです。
ハイドレーションを行うことで、ボタンをクリックした際のイベントが登録され、インタラクティブなWebの画面を表示することができるようになります。
~~movableJavaScriptみたいなわかりやすい単語じゃだめだったのかしら~~

プリレンダリングとは、このサーバー側で事前にHTMLを生成しておくことです。
「Pre」とは「あらかじめ」という意味ですから、こちらはハイドレーションと比較するとそもままの意味で受け取れますね。
Next.jsにはプリレンダリングを行うには、このSSRと後述するSSGのどちらかを選択することになります。

ここまでくると冒頭のハイドレーションとプリレンダリングについての解説も混乱することなく読めそうです。

## SSG スタティックサイトジェネレーション
```mermaid
sequenceDiagram
    actor Developer as 開発者
    participant Build as ビルドプロセス
    participant DB as データベース/API
    actor User as ユーザー
    participant Browser as クライアント（ブラウザ）
    participant CDN as CDN/静的ホスティング

    Developer->>Build: ビルド開始
    Build->>DB: データフェッチ
    DB-->>Build: データ返却
    Build->>Build: 全ページの静的HTMLを生成
    Build->>CDN: 静的ファイルをデプロイ
    Developer->>CDN: デプロイ完了

    Note over User,CDN: ビルド後のユーザーアクセス

    User->>Browser: URLにアクセス
    Browser->>CDN: 静的HTMLリクエスト
    CDN-->>Browser: 事前生成された静的HTML + JavaScript
    Browser-->>User: 完全なページを即時表示
    Browser->>Browser: JavaScriptを実行（ハイドレーション）
    User->>Browser: ユーザーの操作
    alt クライアントサイド更新
        Browser->>Browser: ローカルで状態更新
        Browser-->>User: 即時UI更新
    else 動的データ取得
        Browser->>DB: APIリクエスト
        DB-->>Browser: 最新データ返却
        Browser->>Browser: UIを更新
        Browser-->>User: 更新されたコンテンツを表示
    end
```
今までの2つがリクエスト時にどこかでページを生成していたのに対して、こちらは事前に生成しておいたページをリクエスト時に配信するような形式です。
動的なデータがたくさんあるようなサイトには向きませんが、更新の少ないサイトであれば一度ページを生成してしまえばよいので、そういった条件に合致する場合は非常にパフォーマンスの良い選択肢となるでしょう。

## RSCとは何ぞや？
RSCが登場したことによって、その技術を利用すべくNext.jsがAppRouterをいうルーティングシステムを導入したという話をしましたが、そもそもRSCとは何でしょうか。

https://ja.react.dev/reference/rsc/server-components
> サーバコンポーネントは新しいタイプのコンポーネントです。クライアントアプリケーションや SSR サーバとは別の環境で、バンドル前に事前にレンダーされます。
> 
> React Server Components の “server” とはこの別の環境を指しています。サーバコンポーネントは、CI サーバでビルド時に一度だけ実行することも、ウェブサーバを使用してリクエストごとに実行することもできます。

RSCによって何ができるようになったかというと、「クライアントコンポーネント」「サーバーコンポーネント」というコンポーネント単位でレンダリングを分けることができるようになったという点です。
RSC登場以前は、クライアントコンポーネントしか存在しませんでした。

それまでもCSRとかSSRといった棲み分け自体はありましたが、あくまですべてクライアントコンポーネントであり、「サーバーのみで実行されるコンポーネント」というものはなかったようです。
（ここ勘違いしたせいで混乱しましたが、RSCによってサーバーコンポーネントというものが初めて登場したようです）

TODO
SCが登場したことで何が嬉しかったの？か書く
SCだとできないこと（useStateとかできないよねとか）
逆にSCがあると嬉しいこと（トークンとかの秘密情報はサーバーにしかなくて、クライアントにはわたってこないとか）

## AppRouterにおけるSSR
前述したSSRの図は、RSC登場以前のPagesRouter時代のものでしたが、AppRouterにおいては、ページ単位よりも、更に細かなコンポーネント単位でレンダリングを実行することが可能になりました。

```mermaid
sequenceDiagram
    participant クライアント
    participant サーバー
    participant RSCレンダラー
    participant データソース

    クライアント->>サーバー: ページをリクエスト
    サーバー->>RSCレンダラー: サーバーコンポーネントのレンダリングを開始
    loop コンポーネントツリーの走査
        RSCレンダラー->>データソース: 必要に応じてデータフェッチ
        データソース-->>RSCレンダラー: データを返す
        RSCレンダラー->>RSCレンダラー: サーバーコンポーネントをレンダリング
    end
    RSCレンダラー-->>サーバー: RSC Payloadを生成
    サーバー->>クライアント: 初期HTMLとRSC Payloadを送信
    クライアント->>クライアント: 初期HTMLを表示
    クライアント->>サーバー: クライアントコンポーネント用のJSをリクエスト
    サーバー->>クライアント: クライアントコンポーネント用のJSを送信
    クライアント->>クライアント: RSC Payloadを解析しクライアントコンポーネントをハイドレーション
    クライアント-->>クライアント: インタラクティブなページを表示
```

しれっとRSC Payloadとか言う単語が出てますが、これはSCでのレンダリング結果や、SCからCCに渡すpropsのデータなどをまとめたjsonのようなフォーマットでのメタデータのようなものです。


## PPR(パーシャルプリレンダリング)
~~力尽きたので割愛します~~
~~すごく簡単に言うとRSC登場によってCCとSCの併用が可能になりましたが、さらにSSRとSSGの併用も可能になるようです。またまた、なんだかよくわかりませんね~~


## 参考資料
[一言で理解するReact Server Components](https://zenn.dev/uhyo/articles/react-server-components-multi-stage)
[Next.jsから学ぶWebレンダリング ~React誕生以前からApp Router with RSCまでの流れ~](https://zenn.dev/suzu_4/articles/2e6dbb25c12ee5)
[React Server ComponentsとApp Routerをそろそろちゃんと理解したい](https://qiita.com/newbee1939/items/7ce919f9a1a7153582b8)
[How React 18 Improves Application Performance
](https://vercel.com/blog/how-react-18-improves-application-performance)
[Next.js 公式Rendering](https://nextjs.org/docs/app/building-your-application/rendering)
[React Server Componentsの仕組み：詳細ガイド](https://postd.cc/how-react-server-components-work/)
[Next.js App Router / React Server Components(RSC)を紐解いてみた](https://www.estie.jp/blog/entry/2024/08/05/183235)