Next.jsのドキュメントを改めて読み込んでいたところ、Next.jsは所謂CSRから脱却していることが分かりました。
この記事では、Next.jsが提供しているレンダリングの選択肢や、その選択肢にCSRが必要ない理由について解説します。
併せて、このレンダリングについて気軽に動作確認するためのアプリも作成したため、最後にシェアします。
前提
本記事におけるCSRとは、「ページの(再)読み込み時にブラウザに空のdivタグのようなものが返ってきて、DOMの生成からハイドレーションまで全てブラウザ側で行われるアーキテクチャ」を指します。
1. 一般論:SSR / SSG(static) とは
これらの用語は、使う人によって指すところが微妙に異なる場合がある。
CSR以外に、SSR・SSGについても念の為意味合いを明確にしておく。
1-1. SSRとは
ページの(再)読み込み時、以下の条件を満たすページは、SSRされていると言える
- そのページのHTML生成やハイドレーションより先に、初期描画のためのデータが取得されている
- そのデータはホスティングサーバー上でリクエストごとに取得されたデータである
1-2. SSGとは
ページの(再)読み込み時、以下の条件を満たすページは、SSGされていると言える
- そのページのHTML生成やハイドレーションより先に、初期描画のためのデータが取得されている(SSRと同様)
- そのデータはビルド時に取得されたものである(SSRとの違い)
※Next.jsではStatic Generation=SGと呼んでいるが、便宜上SSGで統一する。
1-3. staticとは
データがない場合には、staticと呼ばれる。
これはSSGの一種とされる場合もある。
例えばNext.jsでは、SSGとstaticを区別しているときもあれば、ドキュメント上staticをSSGの一部として説明している箇所もあり、揺れている。
シーケンスはSSGに近いため、この記事ではstaticはSSGの一種として扱うことにする。
2. Next.jsのレンダリング基本編 ページ再読み込み時
Next.jsのレンダリングは、大きく分けて
- ページの再読み込み時
- 画面遷移時
の2つに分かれる。
このセクションでは、SSR/SSGが強みとする、F5やCmd + Rによるページの再読み込み時から説明する。
一般に、CSRは再読み込みに弱いものの、画面遷移が高速であることが強みである。
次のセクションで、Next.jsのSSR/SSGが画面遷移時においてもCSRに遅れを取らないということを説明する。
2-1. SSR ページ再読み込み
Next.jsでは、ページに対してSSRを指定することができる。SSG対象のページをリクエストすると、以下のようなフローになる。
これは一般的に理解されているフローであると考えられる。
- ブラウザからホスティングサーバにページをリクエストする
- ホスティングサーバーで必要なデータを取得する
- ホスティングサーバーはデータをHTMLに組み込んでブラウザに返す
- ブラウザは返ってきたHTMLをそのまま表示する(続けてReactのハイドレーション等が実行される)
SSGは複雑で、実際にはfallbackやISRといった、データの追加・更新に対応するための手段が提供されているが、ブラウザとホスティングサーバー間のやりとりには大枠違いはない。
2-2. SSG ページ再読み込み
Next.jsでは、ページに対してSSGを指定することができる。
SSR対象のページをリクエストすると、以下のようなフローになる。これも、一般的に理解されているフローであると考えられる。
- (ビルド時にデータを取得してアセットを生成しておく)
- ブラウザからホスティングサーバにページをリクエストする(SSRと同様)
- ホスティングサーバー上ではビルド時に生成したHTMLをブラウザに返す
- ブラウザは返ってきたHTMLをそのまま表示する(SSRと同様)
2-3. CSRは存在しない
Next.jsではCSRを指定することはできず、ページの再読み込み時に空白ページが返されるようなパターンは存在しない。
もちろん、クライアントから直接データを取得することは可能である。
ページの描画後にuseEffectなどを用いてクライアント側でデータをフェッチする。
ただし、ページの初期表示は必ずSSRやSSG(static含む)によって行われることになり、こうしたレンダリング手法にクライアントサイドデータフェッチを組み合わせることになる。
※「Next.jsにCSRは存在しないか」は、結局のところCSRという言葉の定義次第でもある。クライアントサイドデータフェッチをCSRと呼ぶなら、「Next.jsではSSRやSSGと組み合わせてCSRが可能」ということになる。
このような呼び方にすることで、ページ再読み込み時の初期描画時には必ずサーバー側でレンダリングされたHTMLが返ってくるアーキテクチャ(SSR / SSG / static)であることを示唆していると思われる。
どのようなときにクライアントサイドデータフェッチすべきか
あるデータをクライアントサイドデータフェッチすべきか迷うことがあるとすれば、もう一つの選択肢はSSRになるだろう。
SSGは、データの更新頻度や求められる整合性といった性質が大きく異なるためである。
このとき、どちらにすべきかについては、
このページの冒頭にある説明が分かりやすい。
- Client-side data fetching is useful when your page doesn't require SEO indexing,
- when you don't need to pre-render your data,
- or when the content of your pages needs to update frequently.
例えば1画面で収まるTODOアプリがあるとすれば、それはクライアントサイドデータフェッチが向いていると思われる。
ユーザーのTODO追加やステータス更新により、ページ内のデータが頻繁に更新されることになるためである。
一方で、TODOを編集する画面がTODO詳細ページに切り出されているとしたら、SSRが検討できる。
TODO詳細ページのデータは初期表示のタイミングに一度だけ読み込まれれば良いためである。