今回はNuxt3とFirebase v9の環境で、Firebaseの環境変数を.envで開発・本番でそれぞれ分けて使用し、ホスティングする方法を解説します。
今回のゴールは、
- Firebaseにステージングと本番環境の2つのプロジェクトが作成してあり、
- ローカルで開発するときはステージングのFirebaseの環境変数とデータ(Firestoreなど)を使い、
- デプロイはステージングか本番のどちらに行うかをnpm scriptsで切り替えられる
といったところを目指します。
1. .env.stagingと.env.productionを用意
.envは環境変数を指定できるファイルですが、Nuxt3では.env.stagingと.env.production(と.env.local)というファイルを使って環境変数をステージングと本番(とローカル)で分けることができます(ファイル名がこれらで決まっているので.env.stgとかはダメです)。
.env.stagingにステージング、.env.productionに本番のFirebaseの環境変数をそれぞれ書いておきます。
FIREBASE_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_AUTH_DOMAIN=xxxxxxxxxxxxxx
FIREBASE_PROJECT_ID=xxxxxxxxx
FIREBASE_STORAGE_BUCKET=xxxxxxxxxxxxxxxxxxxxx
FIREBASE_MESSAGING_SENDER_ID=xxxxxxxxxx
FIREBASE_APP_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FIREBASE_MEASUREMENT_ID=xxxxxxxxxxxxxx
Nuxt3の.envについて詳しく知りたい方は公式ドキュメントを参考にどうぞ。
>>.env · Nuxt Directory Structure
また、.env.stagingと.env.productionはgithubにpushしないように.gitignoreに忘れずに追記しておきましょう。
# Local env files
.env
.env.*
!.env.example
>>.gitignore · Nuxt Directory Structure
2. nuxt.config.tsに環境変数を追加
Nuxt3の設定ファイルであるnuxt.config.tsに作成した環境変数を使うように追加します。
export default defineNuxtConfig({
// 省略
runtimeConfig: {
public: {
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET,
FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
FIREBASE_MEASUREMENT_ID: process.env.FIREBASE_MEASUREMENT_ID,
},
},
// 省略
});
runtimeConfig内に環境変数を設定できます。public内に書くとクライアントサイドから値にアクセスできます(publicの外側に書くとサーバーサイドでのみ使用できます)。
起動時にFirebaseの初期化(initializeApp()
)を走らせるときにruntimeConfig.public内に書いてないと値を読み取れずにエラーになってしまうので気をつけましょう。
runtimeConfigについて詳しく知りたい方は公式ドキュメントを参考にどうぞ。
>>Runtime Config · Nuxt Advanced
3. initializeApp()時に環境変数を読み込む
Firebaseの初期化を行うjsファイルにnuxt.config.tsに追加した環境変数を読み込むようにします。
import { initializeApp } from 'firebase/app';
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const firebaseConfig = {
apiKey: config.public.FIREBASE_API_KEY,
authDomain: config.public.FIREBASE_AUTH_DOMAIN,
projectId: config.public.FIREBASE_PROJECT_ID,
storageBucket: config.public.FIREBASE_STORAGE_BUCKET,
messagingSenderId: config.public.FIREBASE_MESSAGING_SENDER_ID,
appId: config.public.FIREBASE_APP_ID,
measurementId: config.public.FIREBASE_MEASUREMENT_ID,
};
// Initialize Firebase
initializeApp(firebaseConfig);
});
useRuntimeConfig()
でnuxt.config.tsのruntimeConfig内の値にアクセスできます。public内にあるので、config.public.環境変数名でokです。ちなみにdefineNuxtPlugin()
の中で宣言する必要があります。
流れ的には「.env.stagingと.env.productionに環境変数を設定→その値をnuxt.config.tsで読み込む→さらにその値をjs側で読み込む」という感じですね。
これでFirebase初期化時に環境変数を読み込む準備ができました。
あとはnpm scriptsでホスティング先をステージングと本番で分岐させましょう。
4. ステージング用と本番用にそれぞれホスティングできるようにする
(ここ書き方あってるか若干怪しいですが一応ちゃんとできたので説明します)
Firebaseでホスティングをする際は
firebase use プロジェクト名
で対象のプロジェクトを選択してから、firebase deploy (--only hosting)
をでデプロイ(ホスティング)をする
という手順が必要です。このプロジェクト名
の部分をステージングと本番で分けるという部分がミソです。
これを実現するために、npm scriptsでステージング用にデプロイするコマンドと本番用にデプロイするコマンドの2つを作ります。
- ステージング用にデプロイ→ステージング用のnpm scriptsを実行
- 本番用にデプロイ→本番用のnpm scriptsを実行
という感じで分ければいいということになります。
僕はpackage.jsonに以下のようにコードを書いてできました。
"scripts": {
"build": "nuxt build --dotenv .env.development",
"build:prod": "nuxt build --dotenv .env.production",
"dev": "nuxt dev --dotenv .env.development",
"dev:prod": "nuxt dev --dotenv .env.production",
"generate": "nuxt generate --dotenv .env.development",
"generate:prod": "nuxt generate --dotenv .env.production",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"hosting:stg": "npm run build && npm run generate && firebase use ステージングプロジェクト名 && firebase deploy --only hosting",
"hosting:prod": "npm run build:prod && npm run generate:prod && firebase use 本番プロジェクト名 && firebase deploy --only hosting"
},
(正直build:prod
やgenerate:prod
が必要かどうかは未検証ですが、これでできたのでこのまま紹介しておきます。)
Nuxt3にはdotenvが最初から入っているので、npm scriptsで--dotenv 使用するenvファイル
と書くことでそのenvファイルを使うことができます。上のコードで言えばdev
を使うとステージング用のデータを使ったローカル環境が立ち上がり、dev:prod
を使うと本番用のデータを使ったローカル環境が立ち上がります。
hosting:stg
とhosting:prod
という2つのコマンドを作成し、firebase use
の部分でステージングと本番のどちらにデプロイするかを指定しています。
ちなみに&&
は直列で処理(=左から順番に処理し、処理が終わったら右の処理に進む)という意味です(&
だけにすると並列処理という意味ですべて同時進行で処理します)。
プロジェクト名は以下のコマンドでも確認できます。
$ firebase projects:list
これで、
- ステージングにホスティングしたい→
npm run hosting:stg
- 本番にホスティングしたい→
npm run hosting:prod
という感じでホスティングをステージングと本番で分けることができました!
(dotenvではなくcross-envを使っている記事も見かけましたが、Nuxt3にdotenvが最初から入っているのでcross-envを入れる必要はないと思います。)
ちなみにプロジェクトのルートにおいてあるfirebase.jsonには以下のように書いておきました。
"hosting": {
"public": ".output/public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
}
firebase hostingにホスティングするファイルはNuxt3のnpm run build
とnpm run generate
で生成された.output/publicというフォルダなのでこれを指定しておきます。おそらくこれを書いておかないとエラーになります(もしかしたら最初のFirebaseのセットアップで自動で生成されるのかもしれませんが…)。
まとめ
自分も色々やり方を調べて試したのですがいまいちうまく行かないので色々試して最終的にはできたので記事にまとめました。
色々小難しいことをしている記事もたくさんありましたが自分はこのやり方でできたので、参考になれば幸いです。