こんにちは。Enjoy IT Life管理人の仁科(@nishina555)です。
前回、『【Nuxt】SSR・SSG・SPAにおける『nuxt build』と『nuxt generate』の実行結果の違いまとめ』で、Nuxtで用意されているSSR(Server Side Rendering)、SSG(Static Site Generator)、SPA(Single Page Application)の計3つのモードについて紹介しました。
静的ウェブサイトで運用する場合はSSGかSPAを選択できます。
SSGとは事前に生成した静的ファイルを利用して画面を表示するモードです。
SSGは事前に各画面の静的ファイルを生成するため画面表示が早い反面、コンテンツを更新するたびにビルドが必要という欠点があります。
ランディングページをはじめとした更新頻度の少ないページとSSGは相性がよいです。
一方、同じURLでもユーザーによって画面の見え方の異なるページや、更新頻度の多いページとの相性はあまりよくありません。
SPAとはサーバーサイドでレンダリングを行わず、フロントエンドで画面を組み立てるモードです。
SPAは差分更新のみで画面を変更するため画面遷移が高速である反面、JavaScriptを読み込むため初回のページロードに時間がかかるという欠点があります。
SSGとSPAの実装は異なりますが、『nuxt generate
で生成された成果物を静的ウェブサイトへデプロイする』というプロセスは一緒です。
SSGとSPAの定義がわかっていてもプロセスが同じであるため、言葉だけだと違いがイマイチわかりにくいです。
そこで今回はnuxt generate
による成果物やNuxtアプリケーションの挙動がどのように異なるのか具体例をもとにSSGとSPAの違いについて紹介します。
なお、Nuxtは2.14.1
を利用します。
目次
検証に利用するサンプルアプリケーションについて
SSG・SPAにおけるnuxt generate
およびNuxtアプリケーションの挙動を確認するにあたり、今回はNuxt公式ドキュメントで紹介されているCustom Routesを利用します。
Custom Routesはユーザー一覧画面と各ユーザーの詳細画面が用意されているシンプルなアプリケーションです。
『nuxt generate』による成果物の違いについて
nuxt generate
の実行プロセスや成果物の違いについて紹介します。
SSGの場合
nuxt generate
の実行ログは以下の通りです。
Generated route "/users/xx"
というログからわかるように、各ページの静的ファイルが生成されています。
ℹ Doing webpack rebuild because nuxt.config.js modified
ℹ Production build
ℹ Bundling for server and client side
ℹ Target: full static
✔ Builder initialized
✔ Nuxt files generated
✔ Client
Compiled successfully in 6.12s
✔ Server
Compiled successfully in 624.21ms
Hash: 05e1720be351433f6124
Version: webpack 4.44.1
Time: 6121ms
Built at: 2020/08/10 14:20:38
Asset Size Chunks Chunk Names
../server/client.manifest.json 7.86 KiB [emitted]
LICENSES 389 bytes [emitted]
app.b67a212.js 58.5 KiB 0 [emitted] [immutable] app
node_modules/commons.501805f.js 168 KiB 1 [emitted] [immutable] node_modules/commons
pages/index.fe29326.js 1.51 KiB 2 [emitted] [immutable] pages/index
pages/users/_id.7d0c948.js 1.45 KiB 3 [emitted] [immutable] pages/users/_id
runtime.715f042.js 2.35 KiB 4 [emitted] [immutable] runtime
+ 2 hidden assets
Entrypoint app = runtime.715f042.js node_modules/commons.501805f.js app.b67a212.js
Hash: 93b14cb09a45b6c86e9a
Version: webpack 4.44.1
Time: 625ms
Built at: 2020/08/10 14:20:39
Asset Size Chunks Chunk Names
pages/index.js 6.63 KiB 1 [emitted] pages/index
pages/users/_id.js 6.59 KiB 2 [emitted] pages/users/_id
server.js 87.2 KiB 0 [emitted] app
server.manifest.json 307 bytes [emitted]
+ 3 hidden assets
Entrypoint app = server.js server.js.map
ℹ Generating output directory: dist/
ℹ Generating pages with full static mode
✔ Generated route "/"
✔ Generated route "/users/1"
✔ Generated route "/users/2"
✔ Generated route "/users/10"
✔ Generated route "/users/4"
✔ Generated route "/users/6"
✔ Generated route "/users/5"
✔ Generated route "/users/7"
✔ Generated route "/users/9"
✔ Generated route "/users/8"
✔ Generated route "/users/3"
✔ Client-side fallback created: 200.html
✨ Done in 10.77s.
静的ファイルの出力先であるdist
配下は以下のようになっています。
ルートのindex.html
だけでなく、ユーザー詳細画面(users/:id/index.html
)の静的ファイルも存在しています。
$ cd dist
$ tree -L 6
.
├── 200.html
├── README.md
├── _nuxt
│ ├── LICENSES
│ ├── app.b67a212.js
│ ├── node_modules
│ │ └── commons.501805f.js
│ ├── pages
│ │ ├── index.fe29326.js
│ │ └── users
│ │ └── _id.7d0c948.js
│ ├── runtime.715f042.js
│ └── static
│ └── 1597036839
│ ├── payload.js
│ └── users
│ ├── 1
│ │ └── payload.js
│ ├── 10
│ │ └── payload.js
│ ├── 2
│ │ └── payload.js
│ ├── 3
│ │ └── payload.js
│ ├── 4
│ │ └── payload.js
│ ├── 5
│ │ └── payload.js
│ ├── 6
│ │ └── payload.js
│ ├── 7
│ │ └── payload.js
│ ├── 8
│ │ └── payload.js
│ └── 9
│ └── payload.js
├── favicon.ico
├── index.html
└── users
├── 1
│ └── index.html
├── 10
│ └── index.html
├── 2
│ └── index.html
├── 3
│ └── index.html
├── 4
│ └── index.html
├── 5
│ └── index.html
├── 6
│ └── index.html
├── 7
│ └── index.html
├── 8
│ └── index.html
└── 9
└── index.html
SPAの場合
nuxt generate
の実行ログは以下の通りです。
SPAの場合はSSGと違い、静的ファイルはルート(/
)のみ作成されています。
ℹ Doing webpack rebuild because nuxt.config.js modified
ℹ Production build
ℹ Bundling only for client side
ℹ Target: static
✔ Builder initialized
✔ Nuxt files generated
✔ Client
Compiled successfully in 6.96s
Hash: 47d36e3c6f1bf3363c94
Version: webpack 4.44.1
Time: 6961ms
Built at: 2020/08/10 14:18:13
Asset Size Chunks Chunk Names
../server/client.manifest.json 7.79 KiB [emitted]
LICENSES 389 bytes [emitted]
app.ef33196.js 55.4 KiB 0 [emitted] [immutable] app
node_modules/commons.48315ec.js 168 KiB 1 [emitted] [immutable] node_modules/commons
pages/index.9ce75e2.js 1.51 KiB 2 [emitted] [immutable] pages/index
pages/users/_id.5722ee2.js 1.45 KiB 3 [emitted] [immutable] pages/users/_id
runtime.84feac3.js 2.35 KiB 4 [emitted] [immutable] runtime
+ 1 hidden asset
Entrypoint app = runtime.84feac3.js node_modules/commons.48315ec.js app.ef33196.js
ℹ Generating output directory: dist/
ℹ Generating pages
✔ Generated route "/"
✔ Client-side fallback created: 200.html
✨ Done in 11.78s.
静的ファイルの出力先であるdist
配下は以下のようになっています。
SPAではユーザー詳細画面(users/:id/index.html
)の静的ファイルは存在していません。
$ cd dist
$ tree -L 4
.
├── 200.html
├── README.md
├── _nuxt
│ ├── LICENSES
│ ├── app.ef33196.js
│ ├── node_modules
│ │ └── commons.48315ec.js
│ ├── pages
│ │ ├── index.9ce75e2.js
│ │ └── users
│ │ └── _id.5722ee2.js
│ └── runtime.84feac3.js
├── favicon.ico
└── index.html
Nuxtアプリケーションの挙動の違いについて
実際に起動させたアプリケーションを例に、挙動の違いについて紹介します。
SSGの場合
実際の画面がプレビューで表示されていることから分かるとおり、SSGではレンダリングされた画面がレスポンスとして返ってきます。
レスポンスデータにも具体的な値がすでに書き込まれています。
ユーザー詳細画面も同様です。
このように、SSGでは各画面の静的ファイルを事前に生成しておきレスポンスとして返します。
ユーザー情報なども静的な情報として書き込まれているため、SSGではデータの更新がある度に静的ファイルを再生成する必要があります。
SPAの場合
実際の画面がプレビューに表示されていないことから分かるとおり、SPAでは画面の作成はフロントエンド(ブラウザ)で行っています。
SSGではレスポンスに具体的な値が書き込まれていましたが、SPAの場合はJavaScriptが組み込まれています。
ユーザー詳細画面も同様です。
このように、SPAではJavaScriptの埋め込まれたindex.html
をレスポンスとして返します。
フロントエンドでJavaScriptを読み込むことで画面を表示したり画面遷移を実現したりしています。
まとめ
以上で具体例を用いたSSG・SPAの違いの紹介を終わります。
- SSGでは『nuxt generate』で各画面の静的ファイルが生成される
- SAPでは『nuxt generate』で生成される静的ファイルはルートのみ
- SSGでは静的ウェブサイトからのレスポンス時に画面が作成されている
- SPAでは画面の作成はブラウザ上で行われる
この記事がいいなと思いましたらTwitter(@nishina555)のフォローもよろしくお願いします!