Nuxt.js + firebase デプロイ備忘録

割とハマったので備忘録です。
同じことをしようとしている記事がいくつかあるけど、どれもアレンジされているので自分用に(なるだけシンプルに)書き残しました。

参考文献

【Nuxt.js】Nuxt.js SSRモードでfirebaseにデプロイする手順 2020年版
Quick Nuxt.js SSR prototyping with Firebase Cloud Functions
SSRで作ったnuxt projectをFirebase hostingにデプロイする方法
Nuxt.js(SSR)+FirebaseというWEBアプリの最強最終形態

環境

Mac v11.4
npm v7.0.14
firebase-tools v9.14.0
Firebase blazeプラン(従量課金)

デプロイ時にnode10~を使うので、blazeプランにアップグレード必須。
従量課金なので少なくともテスト時は無料で使えると思う。

Nuxt.jsをセットアップ

npx create-nuxt-app <directory>

使うものだけ選択。AxiosやBootstrap-vueなんかの外部モジュールは後々 functions / package.jsonでも読み込む必要があるので注意。

Firebaseを設定

cd <directory>
firebase init

基本デフォルトでOK。ESLintは不要。

firebase.jsonを編集

{
 "functions": {
   "source": "functions"
 },
 "hosting": {
   "public": "static",
   "ignore": [
     "firebase.json",
     "**/.*",
     "**/node_modules/**"
   ],
   "rewrites": [
     {
       "source": "**",
       "function": "ssrapp"
     }
   ]
 }
}

基本コピペ。
public:staticを指定しておくと便利っぽい。ただしstatic内にindex.htmlがあるとrewritesが発火しないのでそこだけ注意。
rewrites > function:後々設定する関数の名前。こことfunctions / index.js内の関数名は一致させておく。

functions / package.jsonを修正

{
 "name": "functions",
 "description": "Cloud Functions for Firebase",
 "scripts": {
   "serve": "firebase emulators:start --only functions",
   "shell": "firebase functions:shell",
   "start": "npm run shell",
   "deploy": "firebase deploy --only functions",
   "logs": "firebase functions:log"
 },
 "engines": {
   "node": "10"
 },
 "dependencies": {
   "firebase-admin": "^8.6.0",
   "firebase-functions": "^3.3.0",
   "nuxt": "^2.12.2"
 },
 "devDependencies": {
   "@nuxtjs/style-resources": "^1.2.0",
 },
 "private": true
}

nodeのバージョンを10に設定。これがblazeプラン必須の理由。
また、先にも言ったとおり、Axios等の外部モジュールはここにも追加しておく必要がある。良く分からん場合は「dependencies」と「devDependencies」の中身を全部入れておけばOK(ホントはOKじゃない)。

functions / index.jsを作成

const functions = require('firebase-functions');
const { Nuxt } = require('nuxt');
const nuxt = new Nuxt({
  dev: false,
  debug: false,
  buildDir: 'nuxt',
});

exports.ssrapp = functions.https.onRequest(async (req, res) => {
 await nuxt.ready();
 nuxt.render(req, res);
});

コピペ。
ここの関数名(今回はssrapp)を先程のfirebase.jsonと合わせる必要がある。

Buildコマンドを修正して便利化

  "scripts": {
   "dev": "nuxt",
   // ここから
   "build": "nuxt build && npm run build:copy:ssrapp",
   "build:copy:ssrapp": "rimraf functions/nuxt && mkdirp functions/nuxt && cp -R .nuxt/dist functions/nuxt/dist",
   // ここまで追加 or 更新
   "start": "nuxt start",
   "generate": "nuxt generate"
 },

"ルートディレクトリのpackage.jsonを"上記のように更新。間違えないように。これによりビルド時にデプロイするディレクトリにデータをコピーしてくれる。これやらないといくらビルドしても更新が反映されない!とかになる(1敗)。

ちなみに上の"build:copy:ssrapp"はMac用の書き方。
Windowsのときは多分下でいけるはず。。。

"build:copy:ssrapp": "rimraf functions/nuxt && mkdirp functions/nuxt && xcopy .nuxt\\dist functions\\nuxt\\dist\\ /E",

Firebaseにデプロイ

firebase deploy

書いてみるとこれだけ?って感じだけどハマったら結構たいへん。
ちなみに2回目以降のデプロイは、

num run build
firebase deploy

の順番で行いましょう。デプロイするだけじゃだめよ。

トラブルシューティング

まず
functions / index.jsのdebugをtrueにするとより詳細なエラーログが出るのでそうする(本番環境に移行する際はfalseに戻すこと)

const functions = require('firebase-functions');
const { Nuxt } = require('nuxt');
const nuxt = new Nuxt({
  dev: false,
  debug: true, // ここ
  buildDir: 'nuxt',
});

デプロイができない
実際のnuxtプロジェクト自体はここには影響しないことがほとんどなので、だいたいは上記のファイルの記述が間違っているなり環境に合っていないなり。

Firebaseのホスティング先URLに飛んだら403エラー
途中でリージョンを変えたりしてたことにより起こったので、普通は起こらないかも知れない。その時はGCP(Google Cloud Platform)では「asia-northeast1」に飛んでいたのに、Firebase上では「us-central1(初期値)」に飛んでいたりした。下手にいじるのはやめよう。
あと、一応GCPの関数の権限の問題もあるかもなので一応確認しよう。新し目のfirebase-toolsを使っている場合は大丈夫っぽいけど。
IAM によるアクセスの承認 の、「認証されていない HTTP 関数の呼び出しを許可する」参照。出来てたらここが原因ではない。

Firebaseのホスティング先URLに飛んだらinternal server error
モジュールが正しく読み込めてない等で、nuxtプロジェクトが正しく稼働していない状態。上記のpackage.jsonに外部モジュールをちゃんと含めているか確認。

以上

何かあったら追記するかもdesu。

この記事が気に入ったらサポートをしてみませんか?