Monorepoに移行しました
2022.10.06
メンヘラテクノロジーのメインのプロダクトであるメンヘラせんぱいはNuxtとFirebaseで動いています。また、管理画面にはNextを使っており、別のリポジトリで実装しています。今回はこれらをひとつにまとめました
モチベーション
NuxtとFirebaseでプロジェクトをはじめるとルートにNuxt側のsrcディレクトリと一緒にfunctionsというディレクトリが作られると思います
Nuxt側とfunctions側でコードを共有できず、型定義やFirestoreへのCRUDを2回書くはめになります。さらに管理画面なんかも作ると似たコードを3回書くことになります(やばい)
これだと同じコードを何度も書かされるので無駄が多いですし、片方のアプリで加えた変更をもう一方に取り込み忘れ、アプリ間で実装の誤差が出てきてしまうリスクもあります
これらの課題意識から、共通化できるところは共通化してしまいたくなり、monorepoに挑戦しました
ゴール
ディレクトリ構成は次のように形を目指します
menhera
├── packages
│ ├── common: 共通の型定義など
│ ├── console: 管理画面(Next)
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── menhera-senpai: メンヘラせんぱいのフロントエンド(Nuxt)
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── server: cloud functions
│ ├── package.json
│ └── tsconfig.json
├── package.json
├── tsconfig.json
└── yarn.lock
各アプリをパッケージとしてpackagesの中に並べ、各パッケージ内のpackage.jsonに依存モジュールが書かれます。yarn.lockはルートにのみ生成され、これでモジュールをすべて共通で管理することができます
monorepoにはyarn workspacesを使い、commonsには共通化したい型定義を書き、commonsをパッケージとしてimportできるようにしました
実際の作業
それでは実際に移ります
初期設定
まずは空のプロジェクトを作ります
$ yarn init
package.jsonを編集します
// ./package.json
{
"name": "menhera",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": {
"packages": [
"packages/*"
]
}
}
ルートにtsconfig.jsonを追加します。commonは全packageで共通で使いたいのでパスのaliasはこちらに書いておきます
// ./tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"^@/*": ["./packages/common/*"]
},
}
}
ソースコードの移動
それではソースコードを移して、設定していきます
アプリのpackage.jsonのdependenciesは消し、yarn addし直します
$ yarn workspace @menhera/menhera-senpai add hogehoge
tsconfig.jsonとnuxt.config.jsを編集し、パッケージ間でimportできるようにしていきます
nuxt.config.jsの方にもcommonからimportするためのaliasを追記します
// ./packages/menhera-senpai/nuxt.config.js
{
...,
alias: {
'^@': resolve(__dirname, '../common'),
}
}
また、package内のtsconfig.jsonはルートのtsconfig.jsonをextendするようにします
{
"extends": "../../tsconfig.json",
...
}
デプロイの設定
最後にデプロイ設定を修正します
まずfirebase.jsonをルートに移動し、firebase.json内に書いていた諸々のパスを変更します
// ./firebase.json
{
...,
"hosting": {
"public": "./packages/menhera-senpai/dist",
...
},
"functions": {
"predeploy": [
"yarn workspace @menhera/server run lint",
"yarn workspace @menhera/server run build"
],
"source": "packages/server"
},
}
といった感じになります
これでデプロイもできるようになりました🎉
さいごに
monorepoは敷居が高いイメージがあってなかなか挑戦できずにいたので今回できてよかったです
これで本当に開発スピードが上がるのかを今後運用してみないとわかりませんが、少なくともアプリ間のギャップや実装漏れは減らせそうなので効果はありそうです
