概要
Next.jsを取り扱う上で欠かすことのできない「Server Action」と「Server Component」と「Client Component」について簡単にまとめる。
自分はPHP/laravelの開発経験があるので、差分を考えた説明をすることにする。
内容
処理の実行場所として比較されることの多い「Server Action」と「Server Component」と「Client Component」だがそれぞれどのように違うのか、そもそも両者は何者なのかなどについて触れてみようとおもう。
PHP/laravelの場合
処理の流れ
- 画面表示時(HTTPメソッド: GET)
- ルーティング(web.php) → コントローラーアクション(FooController) → 画面(foo.blade.php)
- データ送信時(HTTPメソッド: POST)
- ルーティング(web.php) → コントローラーアクション(FooController)にてデータ保存やリダイレクトなど
画面表示時の詳細(bladeの場合)
- HTTPリクエスト(GET)受け取り
- コントローラーアクションで何かしらの処理
- Bladeテンプレートエンジンがblade → HTML化したHTMLをreturn
- ブラウザにて表示(+ JavaScriptが実行)
Server Action
| 項目 | 内容 | 備考 |
|---|---|---|
| 処理の実行場所(ランタイム) | サーバーのNode.js | |
| 使用方法 |
use serverと記載 |
|
| 用途 | フォーム送信やデータ操作など | |
| PHP/laravelで言うところの・・? | 値受け取りのPOST系ルーティングに 紐づくコントローラーアクションの処理 |
- Next.jsがコードビルド時にServer Actionを検出し、一意のIDを設定、フォーム表示時のHTMLにこのIDを埋め込み
- ブラウザにてフォーム送信(Next.jsが自動生成したPOSTのエンドポイントに、先程のIDとフォームのデータを送信)
- サーバー側で受け取ったIDを使って実行するServer Actionを特定、同様に送られたフォームのデータを用いて処理を実行
laravelは開発者が明示的にフォームデータ受け取りルーティング+コントローラーアクションを記載する必要がある。
Next.jsは受け取りルーティングが自動生成され、値受け取り後の処理はフォームのコンポーネント内部にuse server宣言をして記載
Next.jsは「関連する処理は近くに記載する」という設計思想らしい。
Server Component
| 項目 | 内容 | 備考 |
|---|---|---|
| 処理の実行場所(ランタイム) | サーバーのNode.js | |
| 使用方法 | (何も宣言しない) | |
| 用途 | データ取得、静的なコンテンツ表示 | |
| PHP/laravelでいうところの・・? | DBからデータ取得したりしなかたりして それを画面に表示するときの コントローラーアクション + blade(表示画面の動的制御などをするJavaScript処理無し) |
- HTTPリクエスト受け取り
- サーバーのNode.js上で当該コンポーネントがHTMLに変換(データ取得など必要な処理を実行)
- ブラウザにて表示
laravelで最も一般的とも言えるGET系のルーティングに紐づくコントローラーアクションとそれに紐づく画面用のbladeが一つにまとまってるのがServer Componentらしい。考え方はほぼ一緒で登場人物が違うだけっぽい。
(bladeにscriptタグ、別ファイルでJavaScriptなどの記載がない場合)
| 項目 | Laravelの場合 | Next.js(React)のServer Componentの場合 |
|---|---|---|
| 言語 | PHP | TypeScript → JavaScript(ビルド時にNext.jsが実施) |
| 実行環境 | PHP(サーバー) | Node.js(サーバー) |
| データ取得 | Eloquent | Prisma |
| テンプレートエンジン | Blade | React |
| HTML化 | Bladeエンジン | Reactレンダリング |
Server ComponentはSSRの実装方法のうちの一つである。
SSRは「Server Side Rendering」のことでサーバー側にてHTMLを生成する仕組み全般を指す。
Next.jsの場合、Reactコンポーネントから成るReactテンプレートをReactレンダリングがHTML化するが、そのタイミングでDBから取得した値・配列などを本当の意味での静的なHTMLに入れ込んでいる。
laravelの場合、BladeテンプレートをBladeエンジンがHTML化するが、そのタイミングでDBから取得した値・配列などを本当の意味での静的なHTMLに入れ込んでいる。
「サーバー側にてHTMLを生成する」ことをSSRというらしいので一般的なlaravelを使った画面表示は実はSSRということになる。
ちなみに、Server Componentは上記の説明だと「HTML」のみブラウザに返しているように見えるかもしれない。しかし実際はJavaScriptもブラウザに返しているらしい。このJavaScriptはNext.jsのSPAとしてのふるまい制御用のJavaScriptで、表示画面をリッチにしたり、動的なDOM操作などをするためのJavaScriptではないっぽい。
Client Component
| 項目 | 内容 | 備考 |
|---|---|---|
| 処理の実行場所(ランタイム) | ブラウザ | |
| 使用方法 | use client |
|
| 用途 | 動的な仕組み・動き・処理を画面に施したい場合 | |
| PHP/laravelでいうところの・・? | DBからデータ取得したりしなかたりして それを画面に表示するときの コントローラーアクション + blade(JavaScript処理有り) |
- HTTPリクエスト受け取り
- サーバーのNode.js上で当該コンポーネントがHTMLに変換(データ取得など必要な処理を実行)
- ブラウザにHTML + JavaScriptを返す
- HTMLを表示、JavaScript読み込み(ハイドレーション)が行われ動的なイベントハンドラーなどが利用可能に
- ユーザー操作トリガーなどでDOM更新
laravelでDOM操作したい時はもっぱらそのbladeファイルにscriptタグでJavaScriptの処理を書くか、別ファイル化したJavaScriptのファイルを読み込んで実装する。これと同じ様なことをしたい場合Next.jsではClient Componentを用いるらしい。
laravelでDOM操作したい場合は操作したいタグにid属性を付与して一意に特定できるようにし、JavaScript側でそのid属性の値を指定して操作を行う。Next.jsの場合はその必要は無く、決められた構文で直接returnしているReactテンプレートのタグにonClickなどの命令を書くことができる。
Client Componentは「Client」とついているのでSSRではないのではないかと思ったが、初期表示段階のHTMLはサーバーでレンダリングしてるのでその部分はSSRであり、追加の動的な処理部分がブラウザをランタイムとして実行している。