拡張機能から関数コードベースおよびnpmパッケージへの移行
概要
Firebase Extensionを次のいずれかに移行します。
- ローカルCloud Functionsコードベース(アプリ統合用の
functions/src/) - 公開可能なnpmパッケージ(V2関数をエクスポートする再利用可能なオープンソースパッケージ)
ネイティブCloud Functions機能(宣言的IAM、パラメータ化された構成、SDKライフサイクルフック)を活用し、Destructuring Compatibility Shimを使用して第1世代トリガーを第2世代に最新化します。
対象移行ワークフロー
-
対象A: ローカル関数コードベース(エンドユーザーアプリ統合)
- 出力:
functions/src/配下のコード。設定は.env内。 - デプロイ:
firebase deploy --only functions
- 出力:
-
対象B: 公開可能なnpmパッケージ / 共有可能なパッケージ
- 出力: V2関数をエクスポートする再利用可能なnpmパッケージ
- 構成:
exportsマップ、engines: { "node": ">=22" }、peerDependencies: { "firebase-functions": ">=6.0.0" }を指定したpackage.json - 使用方法: 利用者はパッケージをインストールし、
index.ts(export * from "<package-name>") で関数を再エクスポートします。
コアルールと制約
1. 宣言的IAMとAPI(ローカルオーバーヘッドゼロ)
手動の gcloud スクリプトやコンソール指示ではなく、ネイティブSDK宣言を使用します。
- 必要なGCP IAM権限には
requiresRole("roles/...")を使用します。 - Google APIには
requiresAPI("service.googleapis.com", "Description")を使用します。
2. グローバルパラメータアクセス制限
- トップレベルのモジュール読み込みスコープで決して
.value()を呼び出さないでください。 - グローバルSDKインスタンスは
onInit()内または遅延ゲッターで初期化します。import { defineString } from "firebase-functions/params"; import { onInit } from "firebase-functions/v2"; const dataset = defineString("DATASET_ID"); let client: BigQuery; onInit(() => { client = new BigQuery({ datasetId: dataset.value() }); });
3. V2 同時実行性とコストのパリティ
V2は同時実行性(最大80リクエスト)を有効にします。V1の単一同時実行料金を維持するには、cpu: "gcf_gen1" を設定します。
ステップバイステップ移行実行
ステップ1: 拡張機能リソースの棚卸し
extension.yaml:params→defineString、defineInt、defineBoolean、defineSecretapis→requiresAPI(...)roles→requiresRole(...)lifecycleEvents→afterFirstDeploy&afterRedeployresources→ 第1世代トリガーを第2世代にアップグレード(onDocumentWritten、onTaskDispatched、onRequest)
- ファイルとスクリプト: devDependencies、テストフレームワーク(
jest)、テストスクリプトを維持します。
ステップ2: package.json の構成
name: "<package-name>"、engines: { "node": ">=22" }を設定します。peerDependenciesを設定します。"peerDependencies": { "firebase-admin": "^11.0.0 || ^12.0.0", "firebase-functions": ">=6.0.0" }- ESM/CommonJSとTypeScript宣言(
lib/index.js、lib/index.d.ts)を対象とするexportsマップを構成します。
ステップ3: トリガーをV1からV2にアップグレード
- Firestore:
firebase-functions/v2/firestoreのonDocumentWrittenを使用します。 - タスク:
firebase-functions/v2/tasksのonTaskDispatchedを使用します。タスクをキューに入れる際にEXT_INSTANCE_IDを削除します。 - HTTP:
firebase-functions/v2/httpsのonRequestを使用します。 - レガシー第1世代ハンドラーが
(change, context)を期待する場所で、Destructuring Compatibility Shim({ change, context }、{ snapshot, context })を適用します。
ステップ4: ライフサイクルイベントの変換
拡張機能のライフサイクルイベントを src/index.ts のSDKライフサイクルフックにマッピングします。
onInstall→afterFirstDeploy({ task: { function: "initTask" } })onUpdate/onConfigure→afterRedeploy({ task: { function: "setupTask" } })
ステップ5: パッケージのREADMEとエクスポート手順
以下の内容を含む README.md を生成します。
- インストール手順(
npm install) - 再エクスポートスニペット(
export * from "<package-name>") - パラメータ化された構成
.env参照テーブル - 変更点(拡張機能 vs パッケージ)比較テーブル
注意: 決して npm publish を実行しないでください。