Overview
※ 筆者がたまたま Nuxt3 を弄っていて気づいた話なので最新の動向は GitHub の Discussion を追ってください。
Nuxt3 に移行を始めた当初は Nuxt3 が RC になったばかりで、Static Site Generator (SSG) が実装されていませんでしたが、先日 RC5 で試してみたら nuxt.config.js の defineNuxtConfig
で ssr:false
かつ target:static
の状態でビルドができるようになっていましたので、自分のポートフォリオサイトでは SSR をやめて SSG に移行しました。
Context
あらためて調べてみると公式でも公開されてましたね(まだフルで実装はされていないっぽいです)
そもそも、元々自分が Hosting してるポートフォリオサイトは Firebase 上に構築しているのですが、Nuxt3 に移行したタイミングでは SSR モードでしかビルド & ホスティングができず、CloudFunctions のサービスを SSR 用のサーバーとして使う必要があり、Functions に実装していた固有の実装を諦めた、という背景がありました。
大したページでもなく、そもそも SSR が必要とされるユースケースはなかったので、いい機会だったので元々採用していた SSG モードにして、SSR モードのためだけに占有されていた Functions のリソース開放も兼ねて、ポートフォリオサイトのビルドを作り直しました。
SSG やってみた
公式で記載されている通り、SSG を利用するには defineNuxtConfig
内の ssr
property を false に変更します。
※ nitro を使った prerender の実装についてはべっっと調べてみる予定です。
ssr: false
にした状態で改めて nuxi build
を実行すると以下のように .output
配下に html ファイルが作られるようになります(SSR モードの時はこれが作られませんでした)
Nuxt CLI v3.0.0-rc.5 02:20:51 WARN [kit] [compat] Using extendBuild in Nuxt 3 has no effect. Instead call extendWebpackConfig and extendViteConfig. 02:20:53 ℹ Vite client warmed up in 353ms 02:20:53 WARN 02:20:54 (!) Some chunks are larger than 500 KiB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. ℹ Client built in 1325ms 02:20:54 ℹ Building server... 02:20:54 ✔ Server built in 5ms 02:20:54 ✔ Generated public .output/public nitro 02:20:55 ℹ Initializing prerenderer nitro 02:20:55 WARN 02:20:55 (!) Some chunks are larger than 500 KiB after minification. Consider: - Using dynamic import() to code-split the application - Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/guide/en/#outputmanualchunks - Adjust chunk size limit for this warning via build.chunkSizeWarningLimit. ℹ Prerendering 3 routes nitro 02:20:56 ├─ / (2ms) nitro 02:20:56 ├─ /200 (1ms) nitro 02:20:56 ├─ /404 (0ms) nitro 02:20:56 start Building server... nitro 02:20:56 start Writing server bundle... nitro 02:20:57 ✔ Server built nitro 02:20:57 ├─ .output/server/package.json (307 B) (182 B gzip) ├─ .output/server/index.mjs (458 B) (257 B gzip) ├─ .output/server/chunks/nitro/node-server.mjs.map (57.5 kB) (4.4 kB gzip) ├─ .output/server/chunks/nitro/node-server.mjs (17.1 kB) (5.37 kB gzip) ├─ .output/server/chunks/handlers/renderer.mjs.map (15.6 kB) (2.74 kB gzip) ├─ .output/server/chunks/handlers/renderer.mjs (11.8 kB) (3.83 kB gzip) ├─ .output/server/chunks/app/client.manifest.mjs.map (825 B) (335 B gzip) └─ .output/server/chunks/app/client.manifest.mjs (833 B) (319 B gzip)
prerender 用の2つの html ファイルと server 用の成果物が生成されます。
SSR モードの時の成果物は以下で、HTML が生成されないので SSR と SSG では成果物が異なることがわかります。
Firebase を使っている場合、Hosting 先は .output/public
配下なので変わりませんが、SSG モードにすると index.html がそのままホスティングされます。
また Functions に SSR 用のサーバーを立ててそれ経由でしかホスティングされたサイトにアクセスできませんでしたが、HTML ファイルをポン置きするだけでホスティングできるようになったので Functions の役割は元に戻せます。
というわけで Hosting するものを html に変えて再度デプロイをしてみたところ普通 https://emahiro.dev/ にアクセスすることができました。(もうこれでいいじゃん)
Functions も役目を終えたので元に戻すために改めて firebase init functions
を実行して Functions のファイルを生成しました。
あと変更してみて気づいたことですが、SSG にしてみて感じたのは表示速度が速くなっていました。
おそらく SSR モードの時は Functions を起動するまでの cold start 問題にぶち当たっていたと思われます。
余談
Functions deploy がこける問題
lint と build が predeploy で強制的にかかってしまう
firebase init functions
を実行すると、firebase.json の設定も変更され predeploy で lint と build が実行されてしまいます。
// firebase.json "functions": { "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint" // default "npm --prefix \"$RESOURCE_DIR\" run build" //default ], "source": "functions" }
local では source に指定した path を指定して lint & build をしてくれるのですが、lint は成果物となる js にもかかってしまうこと、そして actions では working directory の path の package.json が使われてしまっており、source フィールドの指定が効いてないなかったことが起因して、command not found が発生して actions から deploy ができなくなっていた問題がありました。
行った対応は以下3つです。
- .eslintignore にコンパイルされた js が入る lib directory を記載して lint 対象から外す。
- predeploy の設定を ignore。
- actions で functions directory に入った状態で lint & build をするように変更。