概要
自分はlaravelの開発経験がある。
Next.jsを触り始めて「あ、これやれることの根本はlaravelとあまり変わらないのかも」と思った。
漠然とNext.jsもlaravelと同じMPAなんだろうなーと思っていた。サーバーサイドでレンダリングしたHTMLをブラウザに返して表示してるだけだし〜って。
SSR = MPAではないことはなんとなく分かっているが、学を進めていくとどうやらNext.jsはSPAっぽいことが書いてあったので恥を覚悟でまとめてみる。
内容
laravelはSSRのMPA、Next.jsはSSRのSPAらしいので下記のような比較差分となる。念の為Next.jsの土台になっているReactも書いておく。
| 仕組み | HTML生成 | ページ遷移 |
|---|---|---|
| laravel | サーバー | リロード有り |
| Next.js | サーバー | リロード無し |
| React | ブラウザ | リロード無し |
ちなみに筆者はMPAとSPAを下記のように理解している。
- MPA:画面遷移時に都度新しいHTMLを受け取り表示
- SPA:サービスアクセス初回に空のHTMLを受け取り、表示コンテンツはURLを用いてJavaScriptが書き換え
laravelの場合で画面表示をする場合、下記のサイクルをどこのGET系URLパスでも実施する。
- HTTPリクエスト受け取り
- サーバーにて紐づく画面のbladeをbladeエンジンがHTML化
- HTMLをブラウザに返す
- 表示
Next.jsはどうやら下記らしい。(便宜上、他画面遷移も含めて説明する。)
- サービスの何処かの画面を表示するためのHTTPリクエスト受け取り
- サーバーにて紐づく画面のReactテンプレートをReactレンダリングがHTML化
- HTML + JavaScriptをブラウザに返す
- 表示
- JavaScript読み込み
- サービス内の他画面に遷移するために
<Link href="/foo">で生成されたリンク※1をクリック - JavaScriptが
/foo画面の表示に必要なデータを取得 - 画面の必要な箇所のみ書き換え
- 表示
※1:Next.jsではリンクを<Link>という組み込みのコンポーネントを用いた方法と、HTMLのアンカータグ(<a>)を用いた2種の方法で生成可能である。<Link>を使うとSPA、<a>を使うとMPAの動作になる。サービス内部リンクは<Link>を、外部リンクは<a>を使うことで用途の棲み分けができている。サービス内部リンクは<Link>の利用が推奨されている。
「HTML + JavaScriptをブラウザに返す」ということで、てっきりSPAはClient Componentに限った話かと思ったが、そういう話ではなくServer Componentだとしても、SPAとしてのふるまいを行うためのJavaScriptはブラウザうに返しているらしい。Client Componentの時にブラウザへ返されるJavaScriptはあくまでDOM操作などのものに言及しているだけで実際はServer ComponentでもJavaScriptはブラウザに返っているっぽい。
Server Component、Client Componentに関しては下記記事を参照いただきたい。
いずれのコンポーネントもURL直接指定で初回アクセスされた場合はSSRで一旦当該画面をブラウザに返す、さらにそこからLinkコンポーネントを用いてサービス内部の画面遷移が行われる場合はSPAでのアクセスとなる。
開発者はこのふるまいをそこまで意識すること無くコンポーネントを用いて実装するだけで良い。
初回アクセスの場合はSSRでサーバーサイド側にてHTMLがレンダリングされて返されるため、React単体の時のように初っ端で空のHTMLが変えることがない。これが「Next.jsはSEOにも強い」といわれる所以らしい。