【Nuxt3×Firebase v9】.envでステージングと本番環境を分けて開発・hostingする方法

【Nuxt3×Firebase v9】.envでステージングと本番環境を分けて開発・hostingする方法JavaScript

今回は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でホスティングをする際は

  1. firebase use プロジェクト名で対象のプロジェクトを選択してから、
  2. 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:prodgenerate:prodが必要かどうかは未検証ですが、これでできたのでこのまま紹介しておきます。)

Nuxt3にはdotenvが最初から入っているので、npm scriptsで--dotenv 使用するenvファイルと書くことでそのenvファイルを使うことができます。上のコードで言えばdevを使うとステージング用のデータを使ったローカル環境が立ち上がり、dev:prodを使うと本番用のデータを使ったローカル環境が立ち上がります。

hosting:stghosting: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 buildnpm run generateで生成された.output/publicというフォルダなのでこれを指定しておきます。おそらくこれを書いておかないとエラーになります(もしかしたら最初のFirebaseのセットアップで自動で生成されるのかもしれませんが…)。

 

まとめ

自分も色々やり方を調べて試したのですがいまいちうまく行かないので色々試して最終的にはできたので記事にまとめました。

色々小難しいことをしている記事もたくさんありましたが自分はこのやり方でできたので、参考になれば幸いです。

ZennでCSS設計の
本を書きました!

「CSS設計をちょっと勉強したけど
結局よくわからなかった…」
そんな人に読んでほしい一冊です!

読んでみる