Cloud Functions 第1世代と第2世代の違い（実務編）


## はじめに
2022年8月からGoogle Cloud : Cloud Functions 第2世代（第二世代・gen2）の一般提供が開始されました。
その性能や第1世代との違いは公式ドキュメントやブログ等でまとめられています。しかし、実際のコードの記述方法や実務上の細かな違いについては公式では不足していたり情報が散り散りになっていたりします。ブログやQiitaにも情報が少なかったため書き記すことにしました。
筆者はまだ経験1年未満のエンジニアなので、初心者の目線で書いています。
特にかけだしエンジニアのための一助となれば幸いです！

## 環境
以下の環境を想定しています。
Firebase for Cloud Functions
node.js




## 基本的な性能の違い
[公式ドキュメント](https://cloud.google.com/blog/ja/products/serverless/cloud-functions-2nd-generation-now-generally-available)にまとめられています。

[他ブログ](https://shinyorke.hatenablog.com/entry/cloud-functions-gen2)でCloud Functions gen2はCloud Functionsの皮を被ったCloud Runです、と記述されていますがその通りです。エンドポイントのURLも完全にCloud Run仕様。
基本的には性能は上がっており、最大実行時間が9分→60分に伸びていたり、ウォームスタンバイによって応答速度が向上していたりします。その分価格は上がっています。


## 実務上の違い

### gen2を使うには？

firebase-functionsのモジュールを使用する際に以下のように記述するだけでOK！

```JavaScript
const functions = require('firebase-functions/v2');
```
現状は```/v2```の記述がなければ第1世代が割り当てられます。


### 関数名
第2世代で関数名に使用できるのはアルファベット小文字と数字のみです。
第1世代で使用できたアルファベット大文字やアンダースコアは使用できません。
以下のようにエラーが出ます。
```Error: (functionName) v2 function name(s) can only contain lower case letters, numbers, hyphens, and not exceed 62 characters in length```

大人しく従いましょう。
ちなみにハイフンは一応使えますが記述方法が面倒です（[参考](https://qiita.com/ane_mone/items/83b497dc405ef54c410a)）。
......正直Cloud Functions第2世代の1番使用しづらいところです。

### 環境変数
リージョンやメモリ、最大インスタンス数などの設定方法です。
第1世代では以下のようにexports以下に紐づけていましたが、
```JavaScript
exports.functionName = functions.region('asia-northeast1').runWith(runtimeOps).https.onRequest(async (req, res) => {
// 関数の内容
}
```

第2世代では以下のように別で記述します。

```JavaScript
functions.setGlobalOptions({
    region: "asia-northeast1",
    memory : "1GiB",
    timeoutSeconds : 3600
});

exports.functionname = functions.https.onRequest(async (req, res) => {
// 関数の内容
}
```



第1世代の書き方で進めると以下のようなエラーが出ます。
```Error: Failed to load function definition from source: Failed to generate manifest from function source: TypeError: functions.region is not a function```



### トリガー
第2世代でも第1世代と同様にhttpトリガーを利用できます。また、イベントトリガーとしてPub/Subトリガー、Cloud Storageトリガー等を使用できます。しかし第1世代で使用できた以下のような書式は使用できないようです。
```JavaScript
// 1時間おきに実行
exports.functionName = functions.pubsub.schedule("0 * * * *").onRun(async (context) => {
// 関数の内容
}
```
→（第2世代の場合）
```Error: Failed to load function definition from source: Failed to generate manifest from function source: TypeError: functions.pubsub.schedule is not a function```

Pub/SubトリガーもGUI上から設定するかデプロイ時にCLIで指定することで利用できるかと思いますが（[公式ドキュメント参照](https://cloud.google.com/functions/docs/calling/eventarc?hl=ja#gcloud)）、ソースコードに組み込んで気軽に定期実行関数を生成できなくなったのは少し不便です。
他にも、第1世代でしか使えないトリガーは存在します（[参考](https://cloud.google.com/functions/docs/calling?hl=ja)）。


### GUI
第2世代ではGUI上のCloud Functionsの関数画面においてエンドポイントのURLが表示されコピーできるようになりました。第1世代では「トリガー」タブを開かないとURLが見れなかったので地味にとても便利。
![mosaic_20230320163153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2991958/853fdd30-dd10-a708-2a1f-60fb2690403a.png)



### 所管
以上になります。他にもありましたら都度アップデートしていこうと思います！
第1世代と第2世代で、思ったより多く細かい仕様や記述方法の違いがあります。
第2世代が完全に優れているかと思いきやそうでもなく、現状はケースに合わせて使い分けるのが良さそうです。１つのプロジェクトの中で第1世代、第2世代を併用することももちろん可能です。

お読みいただきありがとうございました。


##  参考文献

https://cloud.google.com/blog/ja/products/serverless/cloud-functions-2nd-generation-now-generally-available

https://cloud.google.com/functions/docs/calling?hl=ja

https://cloud.google.com/functions/docs/calling/eventarc?hl=ja#gcloud

https://qiita.com/gzock/items/4ae721fad4ed09b3ba86

https://qiita.com/ane_mone/items/83b497dc405ef54c410a

https://dev.classmethod.jp/articles/gcf-gen2-migration/

https://shinyorke.hatenablog.com/entry/cloud-functions-gen2