くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

unjs/nitroをCloud Functions for Firebase v2にデプロイする

unjs/nitroCloud Functions for Firebase(第2世代)してみたときの備忘録(*´ω`*)

Cloud Functions(2nd gen)を試してみたかったこともあるけど、
すんなりデプロイできたので、Cloud Runをつかいたいなら、これでもいいかもしれない。

Cloud Functionsの1st genと2nd genの比較

公式の比較ページはこちら。

機能 Cloud Functions(第 1 世代) Cloud Functions(第 2 世代)
イメージ レジストリ Container Registry または Artifact Registry Artifact Registry のみ
リクエストのタイムアウト 最大 9 分 HTTPトリガーは最大60分 / イベントトリガーは最大9分
インスタンスのサイズ 最大 8 GB の RAM(2 vCPU) 最大 16 GiB の RAM(4 vCPU)
同時実行 関数インスタンスごとに 1 件の同時リクエス 関数インスタンスあたり最大 1,000 件の同時リクエス

第2世代はCloud RunEventarcなので、
同時実行数やインスタンスサイズなどが上限が大幅に上がっている。

ただ、制限事項もあるので注意。

  • 第2世代は、アナリティクスイベントをサポートしていません。
  • 第2世代は、認証ブロックイベントをサポートしていますが、 第1世代と同じ基本認証イベントのセットをサポートしていません。
    第1世代の関数と第2世代の関数は同じソースファイルで共存できるため、
    第2世代の関数と一緒に第1世代のアナリティクスと基本的な Authenticationトリガーを開発してデプロイできます。

少し見てみて、ちょっといいなと思ったのは、 メモリとCPUのスペックをそれぞれ指定できること。

第1世代では、メモリしか指定できず、CPUはメモリの値に依存していたけど、
第2世代では、メモリとCPUをそれぞれ指定できる。

CPUはスペック上げたいけど、メモリはそんないらないときに無駄が多かったけど、
適切なスペックを設定できそうでいい。

ただ、CPUの下限が1/12から1になっているので、
128MBだと、10.5倍の料金になるらしいので注意。
2GM以上だと1倍なので、よく実行される場合はお得かも?

nitroをFirebaseにデプロイする

公式のドキュメントはこちら。

presetが用意されているので、環境変数を指定すると、
Firebase向けのソースとしてビルドしてくれる。

$ NITRO_PRESET=firebase npm run build

NITRO_PRESET=firebaseでしてくれること

プレセットを指定すると、このあたりをよしなにやってくれる。

  • firebase-functionsを使った関数のラップ
  • firebase.jsonの作成(存在しなければ)

ソースはこのあたり。

なので、nitro.config.tsに設定を書いておけば、
firebase-functionsを使った部分は自分で書かなくてもいい。

nitro.config.tsの設定

nitro側での設定はこんな感じ。
ほかにも同時接続数とかいろいろ設定できる。

export default defineNitroConfig({
  firebase: {
    // 第2世代を指定: デフォルトは第1世代
    gen: 2,
    // Node.jsのバージョンを指定: デフォルトは18
    nodeVersion: "18",
    // Cloud Functionsの関数名: デフォルトはserver
    serverFunctionName: "server",
    httpsOptions: {
      region: "asia-northeast1",
      memory: "256MiB",
      cpu: 1,
      maxInstances: 1,
      timeoutSeconds: 30,
    },
  },
});

maxInstancesは指定しないと、たくさんインスタンスができてしまい、
使用量が恐ろしい金額になるため、必ず設定しておく。

nitroではHostingも使う

nitroでビルドすると、.output/はこんな感じになっていて、

.output/
  server/  ... サーバ側の資材
  public/  ... 画像などのpublicAssets

それぞれのデプロイ先はこんな感じ。

  • server/ ... Cloud Functionsにデプロイ
  • public/ ... Hostingにデプロイ

なので、firebase.jsonはこんな感じになる。

画像などのpublicAssetsは、Hostingから返して、
他の動的な部分はrewritesでCloud Functionsに流している。

// firebase.json
{
  "functions": { "source": ".output/server" },
  "hosting": [
    {
      "site": "<your_project_id>",
      "public": ".output/public",
      "cleanUrls": true,
      "rewrites": [{ "source": "**", "function": "server" }]
    }
  ]
}

cleanUrlsとかの設定は、Firebaseのドキュメントを参照。
site.firebasercがないときに必要っぽい。

デプロイしてみる

デプロイする時の流れはこんな感じ

# firebaseコマンドやhostingの設定
$ npm install -g firebase-tools@latest
$ firebase login
$ firebase init hosting

# nitroのビルド
$ NITRO_PRESET=firebase npm run build

# firebase Emulatorを使ってローカルで確認
$ firebase emulators:start

# firebaseへデプロイ
$ firebase deploy --only functions:server,hosting

以上!! めんどくさいことをかなりnitroでやってくれるみたい(*´ω`*)
Nuxtもnitroなので、同じ感じでいけそう。

2nd genは便利だけど、気をつけないといけないこともあるので、
使うポイントはよく考えて導入したい(*´ω`*)

参考にしたサイトさま