10/6/2022
Monorepoに移行しました
メンヘラテクノロジーのメインのプロダクトであるメンヘラせんぱいは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は敷居が高いイメージがあってなかなか挑戦できずにいたので今回できてよかったです
これで本当に開発スピードが上がるのかを今後運用してみないとわかりませんが、少なくともアプリ間のギャップや実装漏れは減らせそうなので効果はありそうです