普段は主にWebAPIサーバーの開発を行なっているため、フロントエンド開発について、SPA(CSR)で知識が止まっていました…。最近近くでRemixを使うプロジェクトも立ち上がってきたので、ベース知識として必要なSSR、SGについて調べたときのメモです。
SSRが出てきた背景
いわゆるSPA(Single Page Application)では、レンダリングはすべてクライアントサイド(CSR)で行われます。サーバーにアクセスした時にブラウザが受け取るHTMLはほぼ空っぽで、ブラウザ内のJavaScriptの処理によって画面がレンダリングされて、初めて意味のあるページになります。
この方式は、ブラウザで初期画面の表示が完了するまでに時間がかかる、検索エンジンにページのほんの一部の情報しか伝わらず、SEO(検索エンジン最適化)ができない、といった問題がありました。
クライアントサイドのレンダリングはReactに代表されるJavaScriptで実装されたライブラリによって行われます。一方、サーバーサイドにもNode.jsというJavaScriptの実行環境があります。だったら、Reactによるレンダリング処理をサーバー側でやらせても良いのではないか。このアイデアを実装したのがSSRという認識です。
当然、ユーザとのインタラクションで画面の表示要素が変わるような動的な部品のレンダリングはクライアントで行う必要があります。しかし、それ以外のもの、つまり1回画面が表示されたあとは変更されないような部品のレンダリングはサーバーサイドで行っても問題ありません。また、動的な部品であっても初期値でのレンダリングは行っておいても良さそうです。そうすれば、ブラウザには、動的な部品以外は出来上がった状態の画面がダウンロードされてくる形となります。その分だけ、クライアントサイドレンダリングの時間は短縮されますし、検索エンジンに渡せる情報も増えます。
Next.jsにおけるSSR
Next.jsにおけるSSRの処理を下記のUdemyのコンテンツで学びました。いろいろなサイトの説明を読みましたがこのUdemyの説明はSSRの仕組みにフォーカスして、シンプルな例でNext.jsの動作が説明されており、とてもわかりやすかったです。
従来のReacdtのCSRのレンダリングでは、ブラウザのJavaScriptランタイム上でReactが動作します。ReactがJSXファイルを評価して仮想DOMを構成し、その結果をブラウザのリアルDOMに反映することで画面が出来上がっていました。
Next.jsによるSSRの場合、Node.js上でReactが動作します。サーバーサイドにはブラウザのリアルDOMは存在しないため、仮想ROMからHTMLを出力し、その結果をブラウザにHTTPレスポンスとして応答します。
Next.jsではReactコンポーネント単位でCSRとSSRを選択できます。どちらを選んだ場合でも、最初にサーバーサイドでのレンダリング処理が行われて、その結果のHTMLがブラウザに渡ります。CSRを指定されたコンポーネントの場合、このHTMLに対して追加でクライアントサイドでのレンダリング処理が行われます。これはHydrationと呼ばれ、サーバサイドでレンダリングされたHTMLをReactの仮想DOMと同期します。これにより、useStateやuseEffectによる動的な更新が可能になります。
従来のSPAによるCSRの処理
1.ブラウザがサーバからHTML、JavaScript、CSSをダウンロードします
2.ブラウザがHTMLからDOMを構成します
3.ブラウザがJavaScriptを実行し、Reactランタイムが仮想DOMを構成します
4.Reactランタイムが仮想DOMをリアルDOMに反映します
Next.jsのSSRの処理
1.サーバーがJavaScriptを実行し、Next.jsがReactの仮想DOMを構成します
2.Next.jsがReactの仮想DOMからHTMLを出力します
3.ブラウザがサーバーからHTML、JavaScript、CSSをダウンロードします
4.ブラウザがHTMLからDOMを構成します
Next.jsのCSRの処理
CSR対象のコンポーネントの場合、SSRの処理の後に追加で下記の処理を実行します。
5.ブラウザがJavaScriptを実行し、Next.jsがHydration処理を行います
Hydration処理により、仮想DOMの構築とリアルDOMとの同期が行われます。
useStateやuseEffectの処理が有効になり、インタラクティブな動作ができるようになります。