はじめに
業務でNext.js×Laravelを使ったアプリケーションを開発しており、その中でNext.jsでCSR,SSG,SSRを使用している。
ここもと、これらがデプロイ方法を左右する奥深いものだと改めて考えさせるきっかけがあったので、勉強した以下のことをこの記事にまとめておく。
①CSR,SSG,SSRについて
②Next.jsの2つのデプロイ方法について
(デプロイの手順、各デプロイ方法でCSR,SSG,SSRの何が使えるのか、どんな環境が必要なのか)
※自分なりに調査したことをまとめているが、これから業務で実運用されているノウハウに触れる予定なので、今後また実運用を通して学んだことを追記していきたいと思う。
①CSR・SSG・SSRについて
CSR(Client Side Rendering)
概要
ブラウザからリクエストがあった際、サーバーから
・ほぼ中身のないHTML
・CSS
・ビルドされたJavaScript
をレスポンスとして返却する。
その後ブラウザ側で、受け取ったHTML
,CSS
,JavaScript
を使って、ユーザーに見せるHTMLをレンダリングする。
メリット(通常の静的ページとではなく、SSG,SSRと比べて)
-
SEO が関係なく、データが頻繁に更新され、また事前に静的にページをレンダリング(プリレンダリング)しておく必要がないページの場合は有用。
-
デプロイが容易。(静的ホスティングさえできれば良い)
デメリット
-
クライアントに対してJavaScriptを送信するので、アプリケーションが大規模になるとJavaScriptの量が膨大になり、レンダリングにかかる時間、つまりページが表示されるまでの時間も長くなる。
-
このときの表示時間は、ユーザーが使用しているデバイスの処理能力や通信環境に依存することになる。
備考
- Next.jsのドキュメントでは、データを事前にレンダリングする必要がない場合は、クライアント側でデータをフェッチすることが推奨されている。
getServerSideProps
リクエスト時にデータをフェッチする必要があるページを事前にレンダリングする必要がある場合にのみ使用してください。サーバーがすべてのリクエストで結果を計算する必要があるため、最初のバイトまでの時間(TTFB)は長くなり、結果はヘッダーを使用するCDNによってのみキャッシュできます(追加の構成が必要になる場合があります)。
データを事前にレンダリングする必要がない場合は、クライアント側でデータをフェッチすることを検討する必要があります。
Data Fetching: getServerSideProps | Next.js
- また、クライアント側でのデータフェッチには
SWR
というライブラリの使用が推奨されている。
Next.jsの背後にあるチームは、SWRと呼ばれるデータフェッチ用のReactフックライブラリを作成しました。クライアント側でデータをフェッチする場合は、これを強くお勧めします。
Data Fetching: Client side | Next.js
SSR(Server Side Rendering)
概要
ブラウザからリクエストがあった際、サーバー側で動的にHTMLを生成し、レンダリング済みのHTMLをレスポンスとして返す。
つまりページのロジックとレンダリングを、CSRではクライアント側(ブラウザ)で行っていたのに対し、SSRでは Node.js
のサーバー上で実行する。
これにより先述のCSRのデメリットを補うことが出来る。
メリット
- CSRと比べて
JavaScript を大量にクライアントに送信するという問題を回避できる。(ユーザーの環境に依存しない)
ブラウザではレンダリング済みのHTMLを受け取るのでSEOにも強い。
- SSGと比べて
データの頻繁な更新に対応できる。
デメリット
-
デプロイには**SSRを実行できる環境(Node.js)**が必要。
-
ユーザーからのリクエストごとにサーバー側で演算を行うので、サーバーサイドが重くなる可能性もある。
SSG(Static Site Generator)
概要
デプロイ時に(ビルドするタイミングで)予めレンダリングを行い、必要なデータを埋め込んだ状態のHTMLを生成しておく。
ユーザーからのリクエストがあった際は、サーバーから既に生成済みのHTMLをレスポンスとして返却する。
メリット
-
CSR,SSRと違って、ユーザーからのリクエストに応じてその場でレンダリングを行うことをしないので、パフォーマンスが良い。
-
デプロイが容易。(静的ホスティングさえできれば良い)
デメリット
- データの更新をWebページに反映させるためにはビルドし直す必要があるので、頻繁に更新されるサイトには向かない。
備考
予め生成したHTMLをユーザーからのリクエストの都度アプリケーションサーバーから返却するのではなく、CDNにHTMLファイルのキャッシュを配置しておき各ユーザーに近いCDNからそのキャッシュを返すことで、よりSSGを有効活用できる。
※ Vercel
は Vercel Edge Network
という CDNをデフォルトで備えている。
②Next.jsの2つのデプロイ方法
Next.jsで作成したアプリケーションのデプロイ方法には、以下の2つの方法がある。
(1) SSRできる環境(Node.js)へデプロイ
(2) 静的ファイルを出力し、静的ホスティングする
(1) SSRできる環境(Node.js)へデプロイ
Next.jsのドキュメントでは、
・Vercel(公式で推奨)
・Node.jsサーバー
・Dockerイメージ
の3つの方法が紹介されている。
デプロイ手順
Next.jsの公式ドキュメントに書かれている3通りの方法をざっくりまとめる。
【Vercelの場合】
- ソースコードをVercelにデプロイする。
- Vercelが自動的にNext.jsを検出して
next build
を実行し、デプロイまで行ってくれる。
【Node.jsサーバーの場合】
- サーバーへソースコードをデプロイし、
next build
を実行する。
(これによりHTML, CSS, JSが最適化された形で、.next
フォルダに出力される。)
2. next start
を実行してNode.jsサーバーを起動する。
【Dockerイメージの場合】
-
Dockerfileを用意する。
-
Docker imageをビルドする。(この時に
next build
が実行されるようにDockerfile
で指示する) -
コンテナをデプロイできる環境へデプロイし、コンテナを起動する。
デプロイする必要があるファイルについて
公式ドキュメントで紹介されている上記の手順では、Next.jsのソースコードを全てデプロイしているように思える。
だが next build
を実行してデプロイの為に最適化した .next
ディレクトリが作られているのだから、実際にデプロイに必要なのは以下のファイルのみであり、ソースコードの全てをデプロイする必要は無いと考えられる。
・ .next
・ node_modules
・ package.json
(・ .env
) ※ブラウザ側で環境変数を使用しない場合は不要。
(・ public
) ※デプロイに必要な画像等が無ければ不要。
(実際にNode.js環境にデプロイ済みのアプリケーションで上記のファイルやフォルダのみをデプロイして動作確認してみたところ、問題なく動いた。)
極力リスク低減する為、サーバーには必要なファイルのみをデプロイする方が良いと考えているが、実運用されているノウハウに触れたことが無いので、色んな会社でどのように運用されているのか知りたい…。
できること
CSR,SSG,SSRのどれでも行うことができる。
※「Next.jsの機能をフル活用できる」と言いたいところだが、この記事では取り上げていないISR(Incremental Static Regeneration)に完全対応しているのは2022年3月29日時点ではVercel
とNetlify
のみらしい。
(他のホスティングサービスでもデプロイ可能ではあるが、サポートされていない?ここはまだまだ勉強不足です。)
デプロイ環境について
要するに Node.js
の実行環境が必要ということだが、少し具体的にいうと、
Vercel
-
Node.js
サーバー - コンテナをデプロイできる環境(
Node.js
のコンテナをデプロイする)
の3通りということになる。
Vercelについてはそのままなので省略。
- Node.jsサーバー
Next.jsのドキュメントでは以下のように書かれている。
Next.jsは、Node.jsをサポートする任意のホスティングプロバイダーにデプロイできます。たとえば、 AWSEC2またはDigitalOceanDropletです。
Deployment | Next.js
- コンテナをデプロイできる環境
こちらもNext.jsのドキュメントから引用する。
Next.jsは、 Dockerコンテナをサポートする任意のホスティングプロバイダーにデプロイできます。このアプローチは、KubernetesやHashiCorp Nomadなどのコンテナーオーケストレーターにデプロイする場合、または任意のクラウドプロバイダーの単一ノード内で実行する場合に使用できます。
Deployment | Next.js
(2) 静的ホスティング
Next.jsのドキュメントに以下のように書かれている。
next export
Next.jsアプリケーションを静的HTMLにエクスポートできます。これは、Node.jsサーバーを必要とせずにスタンドアロンで実行できます。
I’m Advanced Features: Static HTML Export | Next.js
デプロイ手順
手順として必要なことは以下の通り。
-
next build
の後にnext export
を実行することで 、.out
ディレクトリを生成する -
.out
ディレクトリを静的ホスティングのできるサーバーにデプロイする
※以下の記事の方法で、手軽にローカル環境で静的HTMLの動作確認を行うことができる
Next.jsの静的サイト生成(SSG)について確認 - わくわくBank
Next.jsで静的HTMLエクスポートしたアプリをローカルで確認する方法 - Qiita
できること
CSR,SSG,SSRのうち、CSRとSSGは静的ホスティングでも使用できる。
SSRは不可。
デプロイ環境
静的ホスティングさえできれば良い。
色んなデプロイ記事を読むと、具体的には以下のようなプラットフォームが使われていた。
・Netlify
・AWS Amplify Console
・firebase hosting
・GitHub Pages
・Amazon S3
さいごに
改めてNext.jsのドキュメントを読むと、
・データを事前にレンダリングする必要がない場合はSSRではなくCSRを行うようにする
・クライアント側でのデータフェッチにはSWRというライブラリを使用する
ことが推奨されているなど、知らなかったことがあった。
また
・SSRさえ使わなければ静的ホスティングの機能のみのWebサーバーでデプロイすることが出来る
・Next.jsも必要最低限以外はSSRではなくCSRを推奨している
ということを考えると、SSRを使う選択をするケースはかなり少なくなるのかなと思った。
CSR/SSG/SSRの違いは、単純にクライアントサイド/サーバーサイドのどちらでレンダリングするかだったり、パフォーマンス面だけではなく、デプロイ方法やその先にある運用コストも左右するということが分かったので、引き続き勉強していきたい。
参考記事