Firebase Studio終了前の移行入門——Next.js開発環境をローカルとCIへ戻す
Firebase Studioの新規ワークスペース作成停止を受け、Next.js + Firestoreのプロジェクトをローカル開発、Emulator Suite、GitHub Actions、App Hostingへ移行する実践手順を解説します。

はじめに
Firebase Studioを使ってプロトタイプを作っていて、こんな状況はありませんか?
- ブラウザ上では動くが、ローカルで同じ開発環境を再現できていない
- FirestoreやAuthenticationの設定がFirebase Studio内の作業に寄っている
- GitHub Actionsでビルド、テスト、デプロイの入口を固定できていない
- 2026年6月22日以降も新しいワークスペースを作れる前提で運用している
Firebase公式ドキュメントでは、Firebase Studioは段階的に終了すると案内されています。2026年6月22日に新規ワークスペース作成が無効化され、2027年3月22日にFirebase Studio自体が終了し、残ったデータは削除されます。一方で、Cloud Firestore、Authentication、App HostingなどのFirebaseサービスは影響を受けない、と明記されています。
本記事では、架空の経理SaaS「KaikeiBoard」を題材に、Firebase Studio上のNext.js + Firestoreプロジェクトを、ローカル開発、Firebase Emulator Suite、GitHub Actions、Firebase App Hostingへ移す手順を整理します。読み終えると、ブラウザIDE依存ではなく、チームで再現できる開発基盤へ移行する流れがつかめます。
何が変わるのか
Firebase Studio終了のポイントは、「Firebaseのバックエンドが止まる」ことではありません。終了するのは開発環境としてのFirebase Studioです。既存のFirestoreデータ、Authenticationユーザー、App Hostingなどのサービスは引き続き動きます。
ただし、開発フローは見直しが必要です。特に業務アプリでは、ワークスペースに閉じた設定や手作業のデプロイを残したままにすると、引き継ぎや障害対応で困ります。
移行の考え方を表にすると、次のようになります。
| 移行対象 | 移行後の置き場所 | 確認すること |
|---|---|---|
| アプリコード | GitHub repository | package.json、環境変数、ビルド手順 |
| Firestoreルール | リポジトリ内のrulesファイル | 本番ルールとローカルファイルの差分 |
| Firestore indexes | firestore.indexes.json | クエリ追加時にCIで検知できるか |
| ローカル検証 | Firebase Emulator Suite | 本番データへ触らず試せるか |
| デプロイ | App Hosting / GitHub Actions | 誰が、どのブランチから反映するか |
事前準備
KaikeiBoardは、請求書、入金予定、承認ログをFirestoreに保存するNext.js App Routerアプリという想定です。まずは、開発に必要な道具をリポジトリへ明示します。
yarn add firebase firebase-admin
yarn add -D firebase-tools vitest @firebase/rules-unit-testing
Firebase公式ドキュメントでは、Firebase JavaScript SDKはfirebaseパッケージ、Admin SDK for Node.jsはfirebase-adminパッケージとして案内されています。Firebase CLIはfirebase-toolsで提供されています。Security Rulesのユニットテストでは、公式ドキュメントが@firebase/rules-unit-testingを案内しています。
次に、Firebaseプロジェクト設定を初期化します。
firebase --version
firebase init
firebase init emulators
firebase init apphosting
firebase init emulatorsは、利用するエミュレータを選び、ポートや設定をfirebase.jsonへ書き込みます。公式ドキュメント上、Emulator SuiteにはNode.js 16以上とJava JDK 11以上が必要です。App Hosting側はfirebase init apphostingでapphosting.yamlを作成できます。
ハンズオン1: Firebase依存をコードに閉じ込める
最初にやるべきことは、Firebase Studio内の暗黙設定に頼らず、アプリから見えるFirebase初期化をコード化することです。Next.jsでは、クライアントSDKとAdmin SDKを混ぜないように分けます。
// src/lib/firebase/client.ts
import { getApps, initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
};
export const firebaseApp =
getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
export const db = getFirestore(firebaseApp);
サーバー側で管理者権限が必要な処理は、firebase-adminへ寄せます。Firestoreの監査ログを書き込むような処理は、Server ActionやRoute Handlerから呼ぶ形にします。
// src/lib/firebase/admin.ts
import { getApps, initializeApp } from "firebase-admin/app";
import { getFirestore } from "firebase-admin/firestore";
if (getApps().length === 0) {
initializeApp();
}
export const adminDb = getFirestore();
例えば、請求書承認時に監査ログを残す処理は次のように書けます。
// src/app/invoices/[invoiceId]/actions.ts
"use server";
import { FieldValue } from "firebase-admin/firestore";
import { adminDb } from "@/lib/firebase/admin";
export async function approveInvoice(invoiceId: string, reviewerId: string) {
if (!invoiceId || !reviewerId) {
throw new Error("invoiceId and reviewerId are required");
}
await adminDb.collection("auditLogs").add({
action: "invoice.approve",
invoiceId,
reviewerId,
createdAt: FieldValue.serverTimestamp(),
});
await adminDb.collection("invoices").doc(invoiceId).update({
status: "approved",
approvedAt: FieldValue.serverTimestamp(),
});
}
ここで重要なのは、Firebase Studioでたまたま動いていた処理を、そのまま画面コンポーネントに散らさないことです。SDK初期化、Admin権限、業務処理を分けると、ローカル検証とCIの対象が明確になります。
ハンズオン2: Firestore Emulatorで本番データに触らない
移行直後は、本番Firestoreを使って手元確認したくなります。しかし、経理や承認ログを扱うアプリでは危険です。まずEmulator Suiteへ逃がします。
package.jsonには、Firebase CLIを呼ぶスクリプトを置きます。
{
"scripts": {
"dev": "next dev",
"build": "next build",
"test": "vitest run",
"firebase": "firebase",
"emulators": "firebase emulators:start --only firestore,auth",
"emulators:test": "firebase emulators:exec --only firestore,auth \"yarn test\""
}
}
Firestore Emulatorへ接続するクライアント初期化も、開発時だけに限定します。
// src/lib/firebase/client.ts
import { connectFirestoreEmulator, getFirestore } from "firebase/firestore";
export const db = getFirestore(firebaseApp);
if (process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR === "true") {
connectFirestoreEmulator(db, "127.0.0.1", 8080);
}
エミュレータ利用時の環境変数は、.env.localに分けます。
NEXT_PUBLIC_USE_FIREBASE_EMULATOR=true
NEXT_PUBLIC_FIREBASE_PROJECT_ID=kaikeiboard-dev
公式ドキュメントでは、Firestore Emulatorの標準ポートは8080、Emulator Suite UIは4000です。ポートを変えた場合は、firebase.jsonとアプリ側の接続先を必ず合わせます。
ハンズオン3: GitHub Actionsで移行後の入口を固定する
Firebase Studioを離れるなら、「誰の環境では動いた」を卒業する必要があります。最低限、PRでyarn buildが通ることをGitHub Actionsで固定します。
name: Web CI
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "yarn"
- run: yarn install --frozen-lockfile
- run: yarn build
Firestoreルールやエミュレータテストを入れる場合は、別jobに分けると見通しがよくなります。
firestore-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "yarn"
- run: yarn install --frozen-lockfile
- run: yarn emulators:test
この時点では、本番デプロイまで自動化しなくても構いません。まずは「PRで壊れていないこと」「mainに入ったコードが同じ手順でビルドできること」を固定します。
ハンズオン4: App Hosting設定をリポジトリに置く
Next.jsをFirebaseで動かす場合、Firebase App HostingはNext.jsを組み込みサポートしています。公式ドキュメントでは、GitHub連携、Cloud Build、Cloud Run、Cloud CDN、Cloud Secret Managerとの統合が説明されています。
apphosting.yamlには、Cloud Runのリソースや環境変数を記述できます。最初から大きくしすぎず、KaikeiBoardでは小さく始めます。
# apphosting.yaml
runConfig:
minInstances: 0
maxInstances: 5
concurrency: 80
cpu: 1
memoryMiB: 512
env:
- variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
value: kaikeiboard-prod
availability:
- BUILD
- RUNTIME
App Hosting backendは、Firebase CLIでも作成できます。
firebase apphosting:backends:create --project PROJECT_ID
公式ドキュメントでは、このコマンドはFirebase CLI v13.15.4以降で使えると案内されています。実行時にはリージョン、GitHub接続、アプリのルートディレクトリ、ライブブランチなどをプロンプトで選びます。
移行チェックリスト
Firebase Studioの終了日はまだ先でも、2026年6月22日に新規ワークスペース作成が止まるため、移行計画は早めに切るべきです。
| 優先度 | 作業 | 完了条件 |
|---|---|---|
| 高 | GitHubにコードを集約 | ローカルでyarn buildが通る |
| 高 | Firebase初期化をコード化 | Studio外でもFirestoreへ接続できる |
| 高 | Emulator Suiteを設定 | 本番データなしで主要フローを試せる |
| 中 | GitHub Actionsを追加 | PRごとにビルドが走る |
| 中 | apphosting.yamlを追加 | App Hostingの設定がレビュー可能になる |
| 中 | 環境変数を棚卸し | 公開変数と秘密情報が分離されている |
| 低 | デプロイ権限を整理 | main反映と本番反映の責任者が明確 |
参考リンク
- Firebase Studio sunset and project migration
- Firebase App Hosting
- Configure and manage App Hosting backends
- Install, configure and integrate Local Emulator Suite
- Firebase CLI reference
- Add Firebase to your JavaScript project
- Add the Firebase Admin SDK to your server
- Build unit tests for Firebase Security Rules
まとめ
Firebase Studioの終了は、Firebaseを使った開発をやめる話ではありません。むしろ、プロトタイプをチーム開発に耐える形へ移すタイミングです。
Next.js + Firestoreのプロジェクトでは、まずコードをGitHubへ寄せ、Firebase初期化を明示し、Emulator Suiteで本番データから切り離し、GitHub Actionsでビルドの入口を固定します。そのうえで、App HostingやHostingのデプロイ設定をリポジトリに置けば、Firebase Studioに依存しない開発基盤へ移行できます。