🦊

Cloud functions v1/v2 とか node18/20 が共存できるからちょっときて

に公開

そろそろ node18 のサポートが切れます。

18が切れるってことは、新規でv1つくれないと暗に言っています。私はnodeで今回分けてませんが、将来v3できることを推測するなら、みなさんの cloud functins の構成はこうなんじゃね?というお話です。

cloudfunctionPjt/
├── functions-v1/                       ← Cloud Functions v1 構文のみ(Gen1 想定)
│   ├── src/
│   │   ├── index.ts                    ← v1 のエントリーポイント(各関数をexport)
│   │   ├── httpFunctions.v1.ts         ← v1 HTTP系の関数定義(functions.https.onRequest 等)
│   │   ├── firestore.v1.ts             ← v1 Firestoreトリガー関数(functions.firestore.document 等)
│   ├── package.json                    ← firebase-functions v3系 + node18
│   ├── tsconfig.json                   ← TypeScript 設定(target: es2017 等)
│   ├── .env.development                ← [開発用] API_KEYなどの環境変数(dotenv対応)
│   ├── .env.production                 ← [本番用] API_KEYなどの環境変数(dotenv対応)
│   ├── .gitignore                      ← .env, node_modules, lib/ などを除外
│   ├── .eslintrc.js                    ← ESLint 設定(Googleスタイル or Prettier対応)
│   └── scripts/
│       ├── deploy-dev.sh               ← 開発用デプロイスクリプト(firebase use dev)
│       └── deploy-prod.sh              ← 本番用デプロイスクリプト(firebase use prod)
│
├── functions-v2/                       ← Cloud Functions v2 構文のみ(Gen2 想定)
│   ├── src/
│   │   ├── index.ts                    ← v2 のエントリーポイント(各関数をexport)
│   │   ├── httpFunctions.v2.ts         ← v2 HTTP関数(onRequest from v2/https)
│   │   ├── firestore.v2.ts             ← v2 Firestoreトリガー(onDocumentCreated など)
│   ├── package.json                    ← firebase-functions v6系 + node20〜22
│   ├── tsconfig.json                   ← TypeScript 設定(strict モードや ESModules対応)
│   ├── .env.development                ← [開発用] API_KEYなどの環境変数(dotenv対応)
│   ├── .env.production                 ← [本番用] API_KEYなどの環境変数(dotenv対応)
│   ├── .gitignore                      ← .env, node_modules, lib/ などを除外
│   ├── .eslintrc.js                    ← ESLint 設定(v1と統一可)
│   └── scripts/
│       ├── deploy-dev.sh               ← 開発用デプロイスクリプト(--only functions:functions-v2)
│       └── deploy-prod.sh              ← 本番用デプロイスクリプト(--project prod)
│
├── firebase.json                       ← 両 codebase(functions-v1, functions-v2)を定義
│                                        例:
│                                        {
│                                          "functions": [
│                                            { "source": "functions-v1", "codebase": "functions-v1" },
│                                            { "source": "functions-v2", "codebase": "functions-v2" }
│                                          ]
│                                        }
│
└── .firebaserc                         ← 同じ Firebase プロジェクトをエイリアス指定
                                         (例: { "projects": { "dev": "pjt-dev", "prod": "pjt-prod" } })

✅ デプロイコマンド例

内容 コマンド
v1関数すべて firebase deploy --only functions:functions-v1
v2関数すべて firebase deploy --only functions:functions-v2
特定関数のみ firebase deploy --only functions:functions-v1:legacyHello

firebase.json

{
  "functions": [
    {
      "source": "functions-v1",
      "codebase": "functions-v1",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "*.local"
      ],
      "predeploy": [
        "npm --prefix \"$RESOURCE_DIR\" run lint",
        "npm --prefix \"$RESOURCE_DIR\" run build"
      ]
    },
    {
      "source": "functions-v2",
      "codebase": "functions-v2",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "*.local"
      ],
      "predeploy": [
        "npm --prefix \"$RESOURCE_DIR\" run lint",
        "npm --prefix \"$RESOURCE_DIR\" run build"
      ]
    }
  ]
}

functions-v1/package.json v1環境の例

{
  "name": "functions-v1",
  "main": "lib/index.js",
  "engines": {
    "node": "18"
  },
  "scripts": {
    "build": "tsc",
    "lint": "eslint --ext .ts ."
  },
  "dependencies": {
    "firebase-admin": "^9.12.0",
    "firebase-functions": "^3.23.1"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^8.29.1",
    "@typescript-eslint/parser": "^8.29.1",
    "eslint": "^8.0.0",
    "eslint-config-google": "^0.14.0",
    "eslint-config-prettier": "^10.1.1",
    "eslint-plugin-import": "^2.31.0",
    "typescript": "^4.5.5"
  }
}

functions-v2/package.json v2環境の例

{
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "22"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^13.2.0",
    "firebase-functions": "^6.3.2"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.25.4",
    "firebase-functions-test": "^3.1.0",
    "typescript": "^4.9.0"
  },
  "private": true
}

Discussion