👌

【Firebase Hosting】複数(マルチ)サイト構築・運用

2023/06/10に公開

前提

  • firebase init hostingを実行完了していること

サイト構築

サイト一覧表示

まず、サイト一覧を表示してみる。

firebase hosting:sites:list

サイト追加

サイト追加してみる。

siteId="privacy"
firebase hosting:sites:create $siteId

追加したサイトの ID に対して、Target 名を紐付ける

.firebaserc へ紐付け設定追加

コマンド実行すると、自動で設定追加されます。

siteId="privacy"
targetName="privacy"
firebase target:apply hosting $targetName $siteId
.firebaserc の実例
.firebaserc
{
  "projects": {
    "default": "<Firebaseプロジェクト名>"
  },
  "targets": {
    "<Firebaseプロジェクト名>": {
      "hosting": {
        "resume": [
          "resume-<ランダム英数文字>"
        ],
        "privacy": [
          "privacy-<ランダム英数文字>"
        ],
        "namecard": [
          "namecard-<ランダム英数文字>"
        ]
      }
    }
  },
  "etags": {}

Target 名と「ホスティング対象ディレクトリ」を紐付ける

firebase.json へ紐付け設定追加

手動で設定追加する必要があります。
public 属性に「Firebase Hosting へデプロイしてホスティングしたい対象のディレクトリのパス」を指定する。

{
  "hosting": [
    {
      "target": "privacy",
      "public": "privacy",
      "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
    }
  ]
}
firebase.json の実例
firebase.json
{
  "hosting": [
    {
      "target": "resume",
      "public": "resume",
      "ignore": [
        "firebase.json",
        "**/.*",
        "**/node_modules/**"
      ]
    },
    {
      "target": "privacy",
      "public": "privacy",
      "ignore": [
        "firebase.json",
        "**/.*",
        "**/node_modules/**"
      ]
    },
    {
      "target": "namecard",
      "public": "namecard/build/web",
      "ignore": [
        "firebase.json",
        "**/.*",
        "**/node_modules/**"
      ]
    }
  ],
  "emulators": {
    "hosting": {
      "port": 5003
    },
    "ui": {
      "enabled": true
    },
    "singleProjectMode": true
  }
}

デプロイ

エミュレータで事前確認

まずは、ローカル環境のエミュレータでプレビュー確認してみる。

targetName="privacy"
firebase emulators:start --only hosting:$targetName

追加したサイトの channel preview へデプロイ

次に、リモート環境(Firebase Hosting 側の環境)でプレビュー確認してみる。

targetName="privacy"
channelName=$targetName
echo firebase hosting:channel:delete ${channelName} -f
firebase hosting:channel:deploy ${channelName} --only ${targetName} --expires 1h

追加したサイトへデプロイ

エミュレータと channel preview のプレビュー確認で問題なければ、本番サイトへデプロイしてみる。

targetName="privacy"
firebase deploy --only hosting:$targetName

サイト無効化・削除

追加したサイトの無効化

削除とは別。
有効化は、ロールバック or 再デプロイで実現する様子。

siteId="privacy"
firebase hosting:disable -s $siteId

サイト削除

siteId="privacy"
firebase hosting:sites:delete $siteId

サイト運用

シェルスクリプトを利用したデプロイ

channel preview(複数)へデプロイし分けるシェルスクリプト
function hosting_channel_preview_deploy() {

    # 標準入力(キーボード)から1行受け取って変数strにセット
    #
    echo "Target No ----------"
    echo "1. resume"
    echo "2. privacy"
    echo ""

    read -p "Target No? > " str

    # 変数strの内容で分岐
    case "$str" in
      1)
        targetName="resume"
        # siteId="既存のchannel previewを削除してから再デプロイしたい場合、ここにサイトIDを指定"
        ;;
      2)
        targetName="privacy"
        # siteId="既存のchannel previewを削除してから再デプロイしたい場合、ここにサイトIDを指定"
        ;;
      *)
        echo "undefined"
        exit
        ;;
    esac

    channelName=$targetName

    # 既存のchannel previewを削除してから再デプロイしたい場合
    echo firebase hosting:channel:delete ${channelName} --site ${siteId} -f

    firebase hosting:channel:deploy ${channelName} --only ${targetName} --expires 1h
}

hosting_channel_preview_deploy

本番サイト(複数)へデプロイし分けるシェルスクリプト
function hosting_deploy() {

    # 標準入力(キーボード)から1行受け取って変数strにセット
    #
    echo "Target No ----------"
    echo "1. resume"
    echo "2. privacy"
    echo ""

    read -p "Target No? > " str

    # 変数strの内容で分岐
    case "$str" in
      1)
        targetName="resume"
        ;;
      2)
        targetName="privacy"
        ;;
      *)
        echo "undefined"
        exit
        ;;
    esac

    firebase deploy --only hosting:$targetName
}

hosting_deploy

GitHub Actions を利用したデプロイ

dev ブランチへ push した時、Firebase Hosting の Channel Preview へデプロイする(各サイト毎に)
.github/workflows/firebase-hosting-merge_dev.yml
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting channelId dev
"on":
  push:
    branches:
      - dev

jobs:
  if_push_origin_dev_resume:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "resume"
          channelId: "resume"
          expires: "1h"

  if_push_origin_dev_privacy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "privacy"
          channelId: "privacy"
          expires: "1h"

dev ブランチへ push 後、pull request を作成した時、Firebase Hosting の Channel Preview へデプロイする(各サイト毎に)
.github/workflows/firebase-hosting-pull-request.yml
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting channelId prX-dev
"on": pull_request

jobs:
  if_create_pr_resume:
    if: "${{ github.event.pull_request.head.repo.full_name == github.repository }}"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "resume"
          channelId: ""
          expires: "1h"

  if_create_pr_privacy:
    if: "${{ github.event.pull_request.head.repo.full_name == github.repository }}"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "privacy"
          channelId: ""
          expires: "1h"

pull request クローズした時、Firebase Hosting の 本番サイト へデプロイする(各サイト毎に)
.github/workflows/firebase-hosting-merge_main.yml
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting channelId live
"on":
  pull_request:
    types:
      - closed

jobs:
  if_pr_merged_resume:
    if: "${{ github.event.pull_request.merged == true }}"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "resume"
          channelId: live

  if_pr_merged_privacy:
    if: "${{ github.event.pull_request.merged == true }}"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: "${{ secrets.GITHUB_TOKEN }}"
          firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_<Firebaseプロジェクト名> }}"
          projectId: <Firebaseプロジェクト名>
          target: "privacy"
          channelId: live

Discussion