【Next.js】CSR,SSG,SSR,ISRがあやふやな人へざっくり解説する
こんにちは、あきのです。普段はWebエンジニアをやっています。
前書き
仕事でNext.js
を書いているのですがSSG
SSR
ISR
らへんの知識があやふやだったので噛み砕いて解説してみました。間違っているところなどあれば、ご指摘していただけるとありがたいです🙇♂️
以下、本題です。
それぞれの基本的な解説
CSR(クライアントサイドレンダリング)
クライアントサイド レンダリング(CSR)は JavaScriptを使用し、直接ブラウザでページをレンダリングすることを意味します。すべてのロジック、データフェッチ、テンプレーティングやルーティングは、サーバーではなくクライアント上で扱われます。
つまりサーバーではなく、(JavaScriptによって)ブラウザ側でレンダリングする方法です。しかしCSR
(クライアントサイドレンダリング)は大きいアプリケーションの場合、クライアントで処理するJavascriptの量も増えますよね。これに伴い、ユーザーにページを表示させるのが遅くなってしまいます。(ユーザーのデバイススペックに依存してしまう)
上記の問題を解決するために、SSR
(サーバーサイドレンダリング)が出てきます。
SSR(サーバーサイドレンダリング)
CSR
(クライアントサイドレンダリング)のようにロジックやデータフェッチをブラウザで行うのではなく、サーバー側で処理(データフェッチ等を)し、HTMLを構築してクライアント側に返す方式です。 この方法ではCSR
(クライアントサイドレンダリング)のようにクライアント(ユーザーデバイス)のスペックに依存せず、ハイスペックなサーバーでHTMLを構築することができます。
とはいえリクエストごとにサーバーで処理し、HTMLが構築されるため、ユーザーを待たせる時間が長くなってしまいます。そこで、SSG
が出てきます。
SSG(静的サイトジェネレーション)
SSR
の問題(CSR
もですが)として、ユーザーのリクエストを受けてからHTMLを構築するので、時間がかかってしまう、という課題がありました。これを解決してくれるのがSSG
(静的サイトジェネレーション)です。
SSG
(静的サイトジェネレーション)はビルド時にHTMLを構築しておきます。この時、外部APIからのデータフェッチも行います。そしてユーザーからリクエストされた時に事前に構築してあるHTMLを表示します。また、アプリケーションサーバーからHTMLを返すのではなく、CDNにキャッシュしておくことでユーザーに対して高速にページを表示することができます。こうすることにより、SSR
よりもユーザーに対して高速にページを表示させることができます。
しかし、またもや問題が出てきます。しかも今回は二つ。
一つ目は、ビルド時に大量のデータを取ってくることは現実的ではありません。例えば、アマゾンのように巨大なECサイトの場合、ビルド時に全てのデータを取ってきて、HTMLを構築することは難しいでしょう。
この問題はフォールバックが解決してくれます。
二つ目は、リソースの更新が頻繁な場合は、どうなるでしょうか?例えば、ツイッターみたいに複数人がコンテンツを更新するような場合(更新が激しい場合)は、このままのSSG
では情報を表示させることができません。だってビルド時しかデータフェッチしていないのだから。
この問題を解決するために ISR
が使われます。
それぞれ解説していきます。
フォールバック
export async function getStaticPaths() {
return {
paths: [
// 省略
],
//ここ!!
fallback: true
}
}
getStaticPaths()
関数内のfallback
が確認できるかと思います。この値がfalse
の場合、存在しないページにアクセスした時に404ページに飛ばされます。true
にした場合、データフェッチしていない状態のHTMLが返され、その後ブラウザ側でデータフェッチが行われて、HTMLが再構築されます。
同時にサーバー側でも同様にデータフェッチが行われ、HTMLの構築が行われます。次回以降のリクエストでは、サーバー側から完全なHTML(データも含まれた)が返されます。
とはいえ、非完全な状態のHTML(データが含まれていない)でクライアントに送られてしまうので、この部分が欠点ですね。この点も解決できます。
blocking
export async function getStaticPaths() {
return {
paths: [
// 省略
],
//ここ!!
fallback: 'blocking'
}
}
fallback
の値にblocking
を入れることで、データが取得されていないページにアクセスした時、サーバーから不完全な状態でHTMLが送られるなんてことはなく、データフェッチが行われてからHTMLが構築され、クライアント側にHTMLが送られます。
ISR(Incremental Static Regeneration)
export async function getStaticProps(hoge) {
return {
props: { hoge },
revalidate: 10, // ここを追加
}
}
getStaticProps()
関数のreturn内にrevalidate
の値として任意の数字を入れてください。その秒数以降にリクエストがきた時に、サーバー側でデータフェッチを再度行い、HTMLを再構築します。 ここでポイントになってくるのが、リクエストしたユーザーにはキャッシュしていたHTMLを返すということです。
一定期間ごとにサーバーサイドレンダリングを行うことで、高速なページ描画を実現しています。こうすることにより、表示されるデータの更新頻度が高くても新しいデータが表示されるようになりました。
とはいえ、ISR
は常に最新のものがユーザーに届けられるわけではありません。(最初のリクエスト時にはキャッシュされたHTMLが返されるので。)使い分けとしては下記のようなイメージで良いと思います。
- リクエスト時に最新の情報でなくても良い:
ISR
- リクエスト時に最新の情報が出てほしい:
SSR
かCSR(SWR
を使った)
以上です🙇♂️
Discussion
SSR等の用語が分からず色々見ている内にこのページに辿り着きました。それで質問があるのですが、CSRはSPAとはどう違うのでしょうか?