CSR/SSR/SSGはどう選べば良いのか

最近話題のReactServerComponentを触ってみたいと思っていたのですが、その前にそもそもSSRとかSSGに対しての知識が浅くかったので技術選定が出来るようまとめてみました。
Next.jsを前提にしていますが概念的なところを中心に記載したので他のフレームワークにも当てはまると思います。


## レンダリングについて
### プリレンダリング
HTMLの生成をブラウザ側のJavaScriptで全て行うのではなく、Next.jsがあらかじめ各ページのHTMLを生成しておくこと。
プリレンダリングは、パフォーマンスとSEOの向上につながります。

生成された各HTMLは、そのページに必要な最小限のJavaScriptコードと関連付けられています。
ブラウザがページを読み込むと、そのJavaScriptコードが実行され、ページが完全にインタラクティブになります。(このプロセスをハイドレーションと呼びます）

例えばSPAの場合、プリレンダリングがない為ハイドレーション前は何もレンダリングされません。
よってSEO,OGPに弱いとされています。

※Next.jsと生のReactの例

|SSR/SSG(プリレンダリングあり)|SPA(プリレンダリングなし)|
|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/8778741d-7c38-b1e4-bdd7-4fa11fc2a980.png" width="83%" >|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/456cb1f7-dd2e-715a-db13-38113bded002.png">|

## レンダリングの種類
フロントエンドでデータを取得してレンダリングする場合、CSR,SSR,SSGのいずれかで行われます。
それぞれの特徴について見ていきます。

### CSR(Client Side Rendering)
ブラウザ側でデータの取得しページのレンダリングを行います。
#### 特徴
:smile: : リクエスト毎に常に最新の情報が取得され、取得中はローディングアニメーションも表示できる為UXが良い
:thinking: :プリレンダリングされない為SEO/OGPに弱く、ブラウザでJavaScriptを処理する為、レンダリングにかかる時間も長くなる
#### CSRの挙動
遷移先クリック後、データ取得からレンダリングまでにローディングを表示させることが出来る
![CSR.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/854ce63c-8ae9-db56-bb38-90c681bd2354.gif)

### SSR(Server Side Rendering)
サーバー側でデータの取得しページのレンダリングを行います。
#### 特徴
:smile: CSRと同様にリクエスト毎にレンダリングされる為、常に最新の情報が取得され、プリレンダリングされている為SEO/OGPにも強い
:thinking: サーバーでデータの取得をしている為、描画までの速度が遅く、UXが悪い
#### SSRの挙動
遷移先クリック後、データ取得からレンダリングまでサーバーで処理をしている為画面が固まったように見える
![SSR.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/cbef2e85-c808-1db9-c377-9f1455c9e682.gif)

### SSG(Static Site Generation)
ビルド時にデータを取得しレンダリングを行います。
#### 特徴
:smile: プリレンダリングされている為SEO/OGPに強く、既にデータを埋め込んだHTMLを取得しているだけなのでローディングアニメーションが不要なくらい描画速度が高速
:smile: リクエスト毎にデータの取得をしない為サーバーの負荷が軽くなる
:smile: SSGしたファイルはAWSのCloudFrontやVercelなどエッジロケーションから配信することで高速レスポンスを返すことが可能。
:thinking: 取得したデータはビルド時にリクエストして取得ものなので最新のデータとはならない可能性がある
:thinking: 大量のデータをビルド時に全てリクエストするのは時間がかかりすぎる

SSGでは結果整合性（最新ではないデータが表示されることを許容する）場合に使用するべきで、強整合性（常に最新のデータが表示されてほしい）を求める場合は、都度CSR,SSRでのデータ取得を行うべきです。
具体的に下記のようなページはSSGが推奨されます。
・マーケティングページ
・ブログ投稿
・e コマースの商品リスト
・ヘルプとドキュメント

また全てのデータをビルド時に取得するのは規模の大きいアプリケーションでは現実的ではない為、トップページに表示する分などに絞ってSSGする必要があります。


SSGの挙動
データを取得したHTMLをレンダリングしている為高速に画面が描画出来る。
![SSG.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/cb722e3c-01c2-a900-8f9e-10ba9e30da99.gif)

#### CSR,SSR,SSGの特徴

|     |CSR| SSR| SSG | 
| --- |:---:|:---:|:---:|
| データ取得 |リクエスト時|リクエスト時|ビルド時|
| SEO/OGP|:x:|:white_check_mark: |:white_check_mark: |
| UX|:white_check_mark:|:x: |:white_check_mark:|
| 表示速度|:x:|:x: |:white_check_mark:|
| 強整合性|:white_check_mark:|:white_check_mark: |:x:|
| |<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/95a1c16b-9714-ef54-c6c5-603fc92ffb0a.png">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/f5084c63-20ed-f9b9-1a5a-238001f0121b.png">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626314/c7018969-74b8-f215-270c-1bb2bec41b3c.png" >


### ISR(Incremental Static Regeneration)
SSGではビルド時にリクエストを行う為最新のデータを取得するには再度ビルドする必要があります。
そこで一定の時間毎にデータの取得及び再レンダリングをするのがISRです。
ISRでは開発者が設定した時間毎にできるのでデータの鮮度を一定に保つことが出来ます。
とはいえ、一定の時間はキャッシュされた情報が返るのでリアルタイム性が求められるページには不向きというのはSSGと同様です。


## まとめ
強整合性が求められる :arrow_right:  CSR
強整合性 & SEO/OGP対策が必要 :arrow_right:  SSR
結果整合性可 :arrow_right:  SSG(ISR)

## 参考
https://nextjs.org/learn/basics/data-fetching
https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed