はじめまして。最近無性に海外旅行に行きたいと思っているフロントエンドエンジニアの内田です。
Next.jsってページごとに色々なレンダリング方法を柔軟に切り替える事が出来て便利ですよね。
ですが、利用する際にはきちんとそれらレンダリング方法のメリットとデメリットを理解する必要があるのでここにまとめておきたいと思います。
ではいってみましょー!!
■CSR(Client Side Rendering)
そのままなんですが、クライアントサイドでレンダリングするフロントエンド技術手法のアーキテクチャのことを指します。
ブラウザからHTTPリクエストされると、サーバー側はビルドされたJSとCSS、中身ほぼ空っぽなHTMLファイルをHTTPレスポンスとして返却します。
初回アクセス時はHTMLファイルの中身はほぼ空なので何も表示されず、その後初期データを取得してブラウザがHTMLをレンダリングします。
メリット
- ページ遷移によるユーザーストレス軽減。一度読み込んだページはその後必要な部分のコンテンツのみを描画させるため画面全体が再描画されるストレスがなくなる。 よってユーザには優れたUI/UXを提供出来る。
デメリット
- 初回アクセス時にWebサイトのデータをまとめて読み込むので、初回の表示まで時間がかかる。
- クライアントサイドのJavaScriptの処理が増えるので、CPUやメモリーが少ないスマホなどのデバイスでは、操作性が損なわれる可能性がある。
- SEOで不利かもしれない。(初回アクセス時にサーバーから返されるHTMLがほぼ空のファイルなのでクローラーがコンテンツを認識できない場合がある)
- 動的なOGPの設定ができない。OGPの設定はサーバーから返されるHTMLのhead内に情報がないと読み込めない為、動的にページごとにOGPを分ける対応が難しい。
- 直帰率が高いサービスにCSRを採用してもあまりメリットはない。
適したサービス
ユーザーが頻繁にページ遷移やコンテンツの操作するような滞在時間の長いサービスに適している。 SEOをそこまで意識しなくてもいいなにかしらのサービスの管理画面などに利用するのがいいかもしれない。
■SSR(Server Side Rendering)
こちらもそのままなのですが、ブラウザではなくサーバサイドでレンダリングして、クライアントサイドで描画(ペインティング)する手法です。
初回アクセス時はクライアント側からHTTPリクエストが送られて、APIからデータを取得します。
その後、サーバ内で動的にHTMLファイルを生成(Node.jsが実行される)しHTTPレスポンスとしてレンダリング済のHTMLを返します。
メリット
- 初回アクセス時はクライアント側でAPIを叩かないので描画が早い。
- SEOに強い。
- ユーザーの通信環境に左右されにくい。(サーバサイドでレンダリングするので、CPUやメモリーが少ないスマホなどのデバイスでも操作性に影響が少ない。)
デメリット
- SSRするためのNode.jsを実行出来るWebサーバーが必要になる。
- サーバ側の負荷が高い。(サーバのCPU負荷が増える。)
- 上2つの結果、ホスティングサーバの課金がつらくなる。
- 秘匿情報が含まれたページがCDNにキャッシュされた場合、個人情報の漏洩などに繋がる。(Aさんの情報がBさんにも見えちゃう場合が!!)その為、色々な事を考慮するとキャッシュ設定が面倒。
適したサービス
コンテンツ更新頻度の高いサービスなど。動画投稿サービスやSNSサービスが例としてあげられる。 比較的に大規模向け。 サーバサイドの知見がある人がチーム内にいればフロントエンドとしては安心出来るかもしれない。
■SSG(Static Site Generator)
静的サイトジェネレーターの事です。 アプリケーションのビルド時に、APIなどからデータを取得し、HTMLを最初に生成(プリレンダリング)し、 サーバーへのリクエストがあった場合には、この生成されたHTMLファイルを返却します。 また、生成された各HTMLはそのページに必要最小限なJavaScriptコードと関連づけられ、ブラウザによってページが読み込まれると そのページに必要なJavaScriptコードが実行されます。
メリット
デメリット
- ビルド以降、データが更新されてもページに反映されない。
- ページの数やコンテンツの数が多くなるとビルド時間が長くなる。
- 頻繁にデータ更新があるサイトには向かない。
適したサービス
更新頻度の少ないブログやコーポレートサイト等。 比較的に中規模向け。
■ISR(Incremental Static Regeneration)
ISRはインクリメンタル静的再生成という手法を指します。
基本的にはSSGの挙動と同じなのですが、クライアント側のリクエストに対しビルド時に生成された静的ページを返し、 尚且、バックグラウンドで一定期間ごとに静的ページの再生成をサーバー側で行うといったものです。
具体例
export async function getStaticProps() { const res = await fetch('https://.../posts') const posts = await res.json() return { props: { posts, }, revalidate: 20, // In seconds } } export default Blog
SSGで利用する際の非同期関数であるgetStaticPropsからreturnするオブジェクトの中で、revalidate指定を一行追加するだけです。 ここでは例として20秒を指定しました。
初回アクセス(CDNにキャッシュが存在していない状態)から20秒経過後、クライアント側からリクエストがあったら クライアントには既に生成されたページを見せつつ(CDNキャッシュ)、バックグラウンドでデータの再取得及び再レンダリングするページを再生成し、 次のリクエストに対しては再生成されたページを返します。
メリット
- SSGのBuild時間を短縮できる。
- SSRと比較したらDB負荷は軽め。
デメリット
- 現段階ではVercel依存。脱Vercelとなった場合に困る。
適したサービス
常に最新の情報である必要性はないが適度な更新頻度のあるサービス。
■まとめ
Next.jsではページごとにご紹介したレンダリング方法をよしなに選択する事が出来るのでそのページに合った最適なWebパフォーマンスをユーザへ届ける事が出来る事でしょう!! 是非この機会にNext.jsに触れてみてはいかがでしょうか。
■感想
Next.jsは導入するサービスのビジネスモデルを理解してレンダリング選定を間違えなければ高いパフォーマンスを発揮するし便利だよってことー。
参考記事:
Next.js の zero-config の恩恵を受けて SPA を作る
Next.jsのプリレンダリング方式についてまとめてみた - Qiita
ブラウザレンダリングを理解するため簡単にまとめてみた - Qiita
最後に
Wizではエンジニアを募集中です!
興味のある方、ぜひご覧下さい。