【図解】Next.jsのSSRが画面反映されるまでの具体的な流れ

JavaScript

Next.jsのページのレンダリングはデフォルトでPre-rendering、つまりSSR(Server-side Rendering)もしくはSG(Static Generation)です。1
SSRとSGのどちらを採用するかはページ単位で選択可能です。2

今回はSSRを採用したページがリクエストを受け取ってから最終的な画面を表示するまでの過程について紹介します。

Next.jsにおけるSSRの具体的な流れ

Next.jsのSSRの流れを図で表現すると以下のようになります。

Next.jsにおけるSSRの流れ
  1. ブラウザからサーバにリクエストが届く
  2. SSRに必要なPropsをリクエストする
  3. Propsを取得する
  4. SSRを実行する
  5. ブラウザにHTMLでレスポンスを返す
  6. ブラウザ上でCSRを実行する
  7. レンダリング結果をマウントする
  8. マウント後、ブラウザ上で副作用を実行する

以下ではそれぞれの過程について解説をします。

ブラウザからサーバにリクエストが届く

ブラウザでURLにアクセスをするとサーバにリクエストが届きます。

SSRに必要なPropsをリクエストする

サーバでUIを構築するにあたり、必要となるPropsをリクエストします。
PropsのリクエストはgetServerSideProps()で行います。

API経由でデータを取得している場合はAPIサーバへリクエストすることになります。

Propsを取得する

リクエストしたPropsが返され、SSRの準備が整います。

SSRを実行する

取得したPropsをもとにSSRを実行します。
SSRはReactDOMServerを利用して実行します。SSRによってReactのコードからHTMLを生成します。

ブラウザにHTMLでレスポンスを返す

SSRで生成したHTMLをブラウザにレスポンスとして返します。
ブラウザのDevToolsを利用するとSSRのページではHTMLがレスポンスで返ってきていることが分かります。

ブラウザ上でCSRを実行する

Next.jsはSSRの結果を画面へ表示する前にCSR(Client-side Rendering)を実行します。
具体的には以下の処理を実行します。

CSRで実行する処理
  • イベントリスナの登録
  • SSRとCSRのレンダリング結果の比較
  • (レンダリング結果が異なる場合)再レンダリング

この過程のCSRはReactDOM.hydrate()を利用して実行します。

ReactDOM.hydrate()はReactDOMServer、つまりSSRによって作成されたHTMLをクライアント側で再利用するメソッドです。

ReactDOM.hydrate()SSRとCSRのレンダリング結果が一致することを期待します。
結果が一致する場合はCSRによる再レンダリングをスキップ、不一致の場合は再レンダリングをします。

レンダリング結果の不一致はパフォーマンス低下やデザイン崩れの原因となります。
レンダリング結果が一致しない場合はReactアプリケーションが警告をしてくれるので修正するようにしましょう。

警告の解消方法の詳細解説は【Next.js】Hydration時にReact.hydrate()による警告が発生するケースとその解決方法で紹介しています。

レンダリング結果をマウントする

レンダリング結果をマウントします。マウント後、レンダリング結果が画面に反映されます。

マウント後、ブラウザ上で副作用を実行する

副作用とは「JSXあるいはTSXからUIを構築する処理」以外に関する処理のことをいいます。

React.jsによって構築されたUIが画面に表示され、DOMにアクセスできる状態になったタイミングで副作用を実行します。
副作用の実行は、関数コンポーネントであれば副作用フックと呼ばれるuseEffectuseSWR、クラスコンポーネントであればcomponentDidMountcomponentDidUpdatecomponentWillUnmountで行います。

SSRのページでCookieやWindow関数といったブラウザの機能を利用したい場合は副作用で実行する必要があります。

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考資料