Monorepo で Cloud Functions for Firebase へデプロイ
September 08, 2022
はじめに
.NET におけるプロジェクト分割に慣れている身としては、Node.js でも積極的にモジュールを分割しつつ、Monorepo な構成で進めがちなわけですが、そんな構成でいざ世の中の便利サービスを使おうとすると詰まることも多いです。今回は、Monorepo で Cloud Functions for Firebase へデプロイするためのまとめです。
前提
関連ツール
- Yarn v1 系
- Firebase CLI 11.8.0
今回扱うリポジトリ内構造(本題と逸れる内容は省略)
依存関係
Cloud Functions 用パッケージである firebase-functions
がサーバー向けモジュール server
を参照し、server
はサーバー・クライアント共通モジュールである core
を参照。
リポジトリルート
> tree -L 1 .
.
├── README.md
├── firebase.json
├── client
├── core
├── firebase-functions
├── server
├── node_modules
├── package.json
└── yarn.lock
5 directories, 4 files
※関係ない内容は割愛
package.json
{
"private": true,
"workspaces": {
"packages": [
"client",
"core",
"server",
"firebase-functions"
]
},
"devDependencies": {},
"dependencies": {}
}
※関係ない内容は割愛
firebase.json
{
"functions": {
"source": "firebase-functions"
}
}
参考材料
公式ドキュメントから押さえておくべきポイント
- yarn.lock ファイルがプロジェクト内にある場合は、そのロックファイルが優先される。
- 関数をデプロイする際、Firebase CLI では、ローカルの node_modules フォルダを無視する。
file:
接頭辞を使用してローカルの Node.js モジュールを含めることもできる。
観測されたデプロイ挙動
firebase.json
でsource
に指定したディレクトリ外に配置された Node.js モジュールは参照できない。
参考 Issues@Github
方針
上記参考材料をもとに試行錯誤し、
- 何かしらの形で Cloud Functions 用パッケージ内に Node.js モジュールを配置
file:
接頭辞を使用し、配置した Node.js モジュールを参照
が良さそうだと考えました。もちろん、通常の Yarn Workspaces 構成とはギャップがあるため、ギャップを埋めるために何かしらの対応を行う必要があります。
ちなみに、このレベルでのギャップ埋めを許容するのであれば、デプロイ時のみ非公開モジュールの使用も選択肢に上がるかもしれませんが、積極的に採用すべきメリットを見出せなかったため、今回は扱いません。
解決策1
firebase-yarn-workspaces を利用することで問題なくデプロイできました。このパッケージにより、
- Cloud Functions 用パッケージ内に
.firebase-yarn-workspaces
ディレクトリを作成し、Monorepo 参照モジュールをコピー - Cloud Functions 用パッケージの
package.json
で"core": "*"
を"core": "file:.firebase-yarn-workspaces/core"
のように Monorepo 参照をfile:
接頭辞を使用して書き換え
が行われる結果、うまくデプロイできるようになります。
ちなみに、README に記載されている Turborepo を使った例に従えば、上記操作を turbo prune
により作成されたディレクトリで行うことで、既存ディレクトリが汚れるのを防ぐことができる、かつ、yarn.lock
ファイルも最適化されるのでより良い形になると思います。
解決策2
Issues@Github で言及されている通り、
- 参照先を pack し、Cloud Functions 用パッケージ内に配置
- Cloud Functions 用パッケージの
package.json
で"core": "*"
を"file:./core.tgz"
のように Monorepo 参照をfile:
接頭辞を使用して書き換え
でもデプロイできました。ただ、2段階で参照する構成になっているせいか、色々詰まりました。
おわりに
なんとかデプロイできたものの、結局は(turbo prune
で切り出せるものの)リポジトリ内に一時的な差分を作ることにはなるので、(自動化できるものの)本質的ではない定型作業を入れざるを得ない面倒さがありますね。暫定対応と割り切って、公式なサポートを待つ感じでしょうか。