【Nuxt3×SPA×SSR】ハイブリッドレンダリングを駆使してFirebaseでホスティングする
破壊的なアップデートであることを除けば、パフォーマンスやコード量の少なさなど、慣れれば旨みがたくさんのNuxt3です。今回は素敵アップデートの一つ、ハイブリッドレンダリングを試してみます。
先日当ブログを「Nuxt2×SSG」から「Nuxt3×SPA×SSR」にアップデートしてみました。
Firebaseにもハイブリッドレンダリング
に対応したホスティングをしていきます。
1からハンズオン形式で説明しようと思いましたが、とってもボリュームがあるのでそのうち。
今回やりたいこと
従来のNuxt2では、SSG
, SSR
, SPA
の選択肢しかありませんでしたが、Nuxt3へのアップデートにより、静的なページと動的なページをそれぞれ別のレンダリング方式で対応できるようになりました。
- トップページはSPA
- 記事ページではSSR
のような選択肢を選べるようになったのです。
これらの機能を使って、SPAとSSRのルートをそれぞれFirebaseにデプロイしていこうと思います。
ISRという者
ISR = インクリメンタル静的再生成
CDN キャッシュに応答を追加することで、リクエストに対して静的ページを返してくれます。
キャッシュの有効期限が切れたらSSRにて再生成を行うという最強レンダリングモードです。
サポートしているプラットフォームが Netlify または Vercel ということで、今回の対応では省きました。
※ Netlifyへの移行をとっても悩みました
必要な設定
- nuxt.config.ts
- 必要なモジュールを入れる
- firebase.json
- firebase-hosting-merge-xxx.yml
※ 自動デプロイの場合
レンダリングルール
まず、レンダリングルールをルート別に振り分けます
nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { ssr: false },
'/posts/*': { headers: { 'Cache-Control': 'public, max-age=60, immutable' } },
},
nitro: {
preset: "firebase"
},
~~~
})
トップページへのリクエストには静的ページを返す。
記事ページへのリクエストには動的にページを生成して返す。
こちらの設定方法については公式で詳しく説明してくれてます
mode | 指定方法 | プラットフォーム |
---|---|---|
SPA | ssr: false | Firebase, Netlify, Vercel |
SSG | prerender: true | Firebase, Netlify, Vercel |
SSR | 指定なし | Firebase, Netlify, Vercel |
ISR | isr: true | Netlify, Vercel |
SWR | swr: true | Netlify, Vercel |
モジュールを入れる
Nitroのビルドに対応するモジュールを入れます
$ yarn add firebase
$ yarn add --dev firebase-admin firebase-functions firebase-functions-test
Firebaseの設定
firebase.json
{
~~~
"functions": [
{
"source": ".output/server", # SSR用の関数がここに配置される
"codebase": "default"
},
{
"source": "functions",
"codebase": "original",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
],
"hosting": [
{
"target": "front",
"cleanUrls": true,
"rewrites": [
{
"source": "/*",
"function": "server", # SSR用の関数を指定する
"region": "asia-northeast1" # ちょっとテクいことをする
}
],
"public": ".output/public", # 静的ファイルがここに配置される
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
],
{
"target": "admin",
~~~
}
}
※ デプロイした関数にprefixが設定するため、それぞれcodebase
に名前を当てています。
コメントを入れている箇所以外は実装に合わせて変えてもらって大丈夫です。
asia-northeast1 にしたい
Nitroサーバーのデプロイ先は、デフォルトで us-central1
に設定されています。
そのため、デプロイ前に以下のファイルを書き換えなければいけません。
.output/server/chunks/nitro/firebase.mjs
自動デプロイが絡むとちょい手間です。
実はreplaceできる
先ほどのnuxt.config.ts
に変更を加えていきます。
※ Firebase CLI 12.x系だとちょっと違うので注意
export default defineNuxtConfig({
routeRules: {
'/': { ssr: false },
'/posts/*': { headers: { 'Cache-Control': 'public, max-age=60, immutable' } },
},
nitro: {
preset: "firebase",
replace: {
[`functions.https.onRequest`]: `functions.region('asia-northeast1').https.onRequest`,
}
},
~~~
})
手で書き換える必要がなくなりました!うれしい
自動デプロイ(Git Actions)
SPA, SSRと分けているため、HostingとSSR用関数を分けてデプロイします。
name: Deploy to Firebase on merge
'on':
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: yarn
- name: Create .env file
run: |
touch .env
echo "${{ secrets.ENV_PRD }}" > .env
cat .env
- name: 📥 Download
run: yarn && yarn build
- name: 🚀 Deploy Server
run: npx firebase-tools deploy --only functions:server
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
- name: 🚀 Deploy Hosting
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_XXX }}'
channelId: live
projectId: xxx
target: front
おわり
実装上、SPAの部分もサーバーサイドで生成されるようなわけのわからん形です。
ただ、クライアントサイドでレンダリングされるので、レスポンシブ対応などが割と楽だったら、隠れた旨みでもあります。
当ブログの実装とはちょいちょい違いますが、SSRへの移行は割とすんなりといきました。
Firebaseの認証やVuetifyのSSR対応など、1から実装するには本来もう少し範囲は広めです。
Nuxt3×SSRはまだまだ知らない箇所が多いので、今後この記事も修正しつつアウトプットしていこうと思います。