【Next.js】SSRとSG(SSG)のPre-renderingの挙動の違い

JavaScript

Next.jsの公式ドキュメントによるPre-renderingの説明は以下の通りです。1

Next.jsを利用したPre-rendering
  1. 初期ロード: プリレンダリングされたHTMLが表示される
  2. JSがロードされる
  3. Hydration: Reactコンポーネントが初期化され、アプリがインタラクティブになる

上記のプロセスを手元のローカル環境で確認したところ、SSRとSGで初期ロードのタイミングが異なっていたので紹介します。

検証環境のnextは11.1.2を利用しています。

『静的なHTMLファイルを事前に生成する仕組み』はStatic Site Generation(SSG)という呼び名で広く知られていますが、Next.jsの公式ドキュメントではStatic Generation(SG)と呼んでいます。
本記事では公式ドキュメントの定義に従い、SGの略語を利用します。

今回利用するサンプルアプリケーション

初期画面の表示とCSRの実行タイミングを検証するため、以下のようなサンプルコードを用意しました。
クライアント側(typeof window !== 'undefined'の時)のレンダリングはwhile (i < 3000000000) i++;によって擬似的に遅い処理となっています。

import type { NextPage } from "next";

const Hydrate: NextPage = () => {

  const hydrateExample = () => {
    if (typeof window !== 'undefined') {
      let i = 0;
      while (i < 3000000000) i++;
      return <div>This is Client</div>
    } else {
      return <div>This is Server</div>
    }
  };

  return <>{hydrateExample()}</>;
};

export default Hydrate;

なおNext.jsでは、サーバサイドとクライアントサイドのレンダリング結果は一致していることを期待しています。
今回は検証のためにあえてサーバサイドとクライアントサイドでレンダリング結果の異なるコンポーネントを用意しましたが、本来であれば不適切な実装です。

SSRの場合: CSRが完了するまで画面表示されない

Next.jsは開発モードで起動する場合、SGの画面もSSR(Server-side Rendering)になる2ことを利用して、yarn devにて当該画面を確認しました。

SSRの場合、画面がロード中になり、しばらくしてから『This is Client』と記載された画面が表示されました。
つまり、SSRの場合はCSR(Hydration)が完了したタイミングで初期画面が表示されるということがわかります。

SGの場合: サーバから取得したHTMLが表示され、遅れてCSRの結果が反映される

yarn build && yarn startで起動して当該画面を確認しました。

SGの場合、『This is Server』と記載された画面がすぐに表示され、しばらくしてから『This is Client』の文言に変わりました。
つまり、SGの場合は初期画面を表示後、CSR(Hydration)が実行されるということがわかります。

さいごに

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