🔥

Firebaseで複数プロジェクト・複数サイトを扱う方法

2024/10/22に公開

Firebase の公式ドキュメントには複数サイトや複数プロジェクトを扱うそれぞれ単体の方法は書かれているのですが組み合わせた場合の方法を探したところありませんでした。また、方法の一部としてコマンドは書かれていても各種設定ファイルの内容については説明がなかったりして困ったのでその辺りについて調べた事を共有します。

Firebase CLI の初期設定

Firebase CLI リファレンス  |  Firebase ドキュメント
説明上必要になる知識も出てくるので簡単に紹介しておきます。

Firebase CLI を利用するには下記のコマンドで Google アカウントの認証を行う必要があります。

firebase login

認証等に問題がなければ以下のコマンドでアクセス権のあるプロジェクト一覧が確認できます。

firebase projects:list

リポジトリ等に Firebase のプロジェクトディレクトリがない場合は初期化が必要です。基本的には Hosting のサイト以外に Cloud Functions なども利用する事が多いのでリポジトリルートとする場合が多いですが、デプロイ対象となるディレクトリが明確ならサブディレクトリでも問題ないです。

firebase init

いくつかの質問のあとに firebase.json.firebaserc が作成され、それぞれの役割は以下の通りです。

  • firebase.json
    • Firebase の各種サービスの構成や設定を行うファイル
  • .firebaserc
    • プロジェクトエイリアスと複数のデプロイターゲットを扱う際の設定を行うファイル
    • プロジェクト ID が記載されるので public リポジトリの場合は .gitignore に登録推奨

それぞれのファイルの具体的な設定方法は後述します。

複数プロジェクト

Firebase CLI リファレンス  |  Firebase ドキュメント

開発環境、ステージング環境、本番環境のように同じ構成を異なるプロジェクトにデプロイしたい場合など、複数のプロジェクトを扱う際の設定とコマンドについての説明です。

複数のプロジェクトを扱いたい時は .firebaserc にエイリアスの定義を追加します。

{
  "projects": {
    "default": "default-project-id",
    "staging": "staging-project-id",
    "production": "production-project-id"
  }
}

エイリアスの定義は firebase use --add コマンドによる対話形式でも追加できます。
default は特別なエイリアス名で使用するプロジェクトの切り替えを行っていない場合に使用されるプロジェクトです。複数のプロジェクトを扱う際は操作ミスなども考慮して default は別名に変えておいた方が安全です。

firebase use <PROJECT_ID | ALIAS>

プロジェクトの切り替えは上記のコマンドで行います。firebase use staging と定義したエイリアスを使う以外にプロジェクトIDを指定する事もできます。

プロジェクトを切り替えると以降に実行するコマンドはそのプロジェクトに対して適用されます。また、firebase deploy --project=staging のように --project オプションでコマンド単位で対象プロジェクトを変更する事もできます。

複数サイト

Firebase CLI リファレンス  |  Firebase ドキュメント
デプロイ ターゲット  |  Firebase ドキュメント
ホスティング動作を構成する  |  Firebase Hosting
複数のサイト間でプロジェクトリソースを共有する  |  Firebase Hosting

1 プロジェクトで複数のサイトを扱うにはデプロイターゲットの設定を行います。この機能自体は Firebase Hosting に限らず Functions や Storage など他のサービスも含めて複数のターゲットを扱う為の機能なのでサイト以外も同様の設定で行えます。

設定を行う前にまず先にリソースを作成します。Hosting のサイトの場合は Firebase の Web コンソールもしくは下記のコマンドで作成できます。site-id はグローバルで一意である事が必須です。

firebase hosting:sites:create <site-id>

サイトが作成できたらデプロイターゲットとして設定します。設定は下記のコマンドもしくは .firebaserc を直接編集する事で行えます。

firebase target:apply <type> <target-name> <resource-identifier>
  • type: hosting や functions など Firebase のリソースの種類
  • target-name: 作成するターゲットの名前
  • resource-identifier: site-id などリソースを識別する為の ID

.firebaserc を直接編集する場合の構造は以下の通りです。
上記のコマンドの target-namemainadmin でそれぞれに対応する resource-identifiermain-site-idadmin-site-id の場合に相当します。

{
  "projects": {
    "default": "default-project-id"
  },
  "targets": {
    "default-project-id": {
      "hosting": {
        "main": [
          "main-site-id"
        ],
        "admin": [
          "admin-site-id"
        ]
      }
    }
  }
}

firebase-tools/src/rc.ts at master · firebase/firebase-tools
補足: TypeScript の型定義は以下のようになっています。

export interface RCData {
  projects: { [alias: string]: string };
  targets: {
    [projectId: string]: {
      [targetType: string]: {
        [targetName: string]: string[];
      };
    };
  };
  etags: {
    [projectId: string]: Record<EtagResourceType, Record<string, string>>;
  };
}

デプロイターゲットの設定が出来たら firebase.json にそれぞれのターゲットの構成を設定します。hosting の値を配列にして .firebaserctarget-name.firebaserctarget の値が対応するように設定して下さい。

{
  "hosting": [
    {
      "target": "main",
      "public": "packages/main/dist",
      "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
    },
    {
      "target": "admin",
      "public": "packages/admin/dist",
      "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
    }
  ]
}

以上の設定で firebase deploy 時に複数のサイトがデプロイできるようになります。また、特定のサイトのみをデプロイしたい時は firebase deploy --only hosting:TARGET_NAME で指定する事ができます。

複数サイト x 複数プロジェクト

デプロイ ターゲット  |  Firebase ドキュメント
ホスティング動作を構成する  |  Firebase Hosting
複数のサイト間でプロジェクトリソースを共有する  |  Firebase Hosting

複数サイトを複数プロジェクトに対応するには .firebaserctargets にプロジェクトのデプロイターゲットの定義を追加する事で行えます。

{
  "projects": {
    "default": "default-project-id",
    "staging": "staging-project-id"
  },
  "targets": {
    "default-project-id": {
      "hosting": {
        "main": [
          "main-site-id"
        ],
        "admin": [
          "admin-site-id"
        ]
      }
    },
    "staging-project-id": {
      "hosting": {
        "main": [
          "staging-main-site-id"
        ],
        "admin": [
          "staging-admin-site-id"
        ]
      }
    }
  }
}

上記は複数サイトで紹介した設定例に staging 用のプロジェクトを追加した設定例です。
site-id はグローバルで一意になっているので各プロジェクトのデプロイターゲットをどの site-id にデプロイするのかの対応付けをここで行う形です。

基本的にはこれで設定が完了し firebase use で切り替えるか firebase deploy --project でプロジェクトを指定すれば、複数サイトを別プロジェクトにデプロイする事が出来るようになります。

ただし、Cloud Run と連携させている場合には注意が必要です。Cloud Run と連携するには firebase.jsonhosting.rewrites の設定を以下のように定義します。

{
  "hosting": [
    {
      "target": "main",
      "public": "packages/main/dist",
      "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
      "rewrites": [
        {
          "source": "/api",
          "run": {
            "serviceId": "api-server",
            "region": "asia-northeast1"
          }
        }
      ]
    },
  ]
}

serviceId に Cloud Run で動作させているサービス名を指定するので複数のプロジェクトで運用する際には全てのプロジェクトで同じサービス名にする必要があります。異なるサービス名をつける運用も可能ですが、プロジェクトが増える毎にサイト数分の hosting target の設定を追加する事になるので、扱うサイト数とプロジェクト数が固定でない限りは避けた方がいいでしょう。例えば、mainadmin があるサイトの構成だとプロジェクトが増える毎に project-name-mainproject-name-admin の設定を firebase.json に追加し、.firebaserc にその対応付けを追加して行くことになります。

Discussion