Lernaを使ってバラバラのExpoのプロジェクトとFirebaseのプロジェクトをmonorepoにしてみる
僕の場合、Expoでアプリを開発する時は、Firebaseを使うことがほとんどである。認証周りとかFirestoreとか便利だし。
ただ、それぞれ別々のリポジトリとして管理していると、いちいちフォルダ間の移動が大変だったりどこにどのファイルを作ったかを忘れたりと面倒なことが多々起こる。ファイルを探すのに指を使うのはエネルギーを消費するので、極力疲れることは避けたい。
なので、monorepoとして管理できたら、たびたび発生するめんどうくさい問題は解決するのではないかと考えた。
いろいろ調べた結果Lernaを使うと良いらしいことがわかったので、今回はLernaを用いてExpoとFirebaseのプロジェクトをひとつのmonorepoとしてまとめて管理する方法を、将来の自分のために残しておこうと思う。
作業環境
MacBook Air (13-inch, Mid 2012)
macOS Catalina 10.15.7
注意事項
expo-yarn-workspaceを使ってexpoをmonorepoに対応させているため、Windowsだとうまく動かない可能性が出てくると思う。ご注意を。
セットアップ
まずはじめに、monorepo用のディレクトリを作成して中に移動する。 そのディレクトリ内でlernaをインストールする。 そして、Independent modeでinitを実行する。
$ mkdir lerna-repo && cd $_ # / $ yarn add --dev lerna $ yarn lerna init --independent
ルートディレクトリにあるpackage.jsonを編集する。
# /package.json { "name": "lerna-repo", "private": true, "workspaces": [ "packages/*" ], "devDependencies": { "lerna": "^4.0.0" } }
次に、ルートディレクトリにあるlerna.jsonを編集する。 Indepdendentモードでinitを実行したので、versionがindependentという値になっている。 デフォルトのモードだと0.0.0になっている。
# /lerna.json { "packages": [ "packages/*" ], "version": "independent", "npmClient": "yarn", "useWorkspaces": true, "command": { "publish": { "ignoreChanges": ["*.md"], "message": "chore: publish" } } }
.gitignoreファイルをここいらで作成しておく。
# / $ touch .gitignore
# /.gitignore node_modules/ commands/* .env # macOS .DS_Store
Expoプロジェクト
続いてexpoプロジェクトをpackages配下に置くために、packagesフォルダに移動する。
expo init
コマンドを実行してexpoプロジェクトを作成する。
もしくは、すでにリモートリポジトリにexpoプロジェクトがある場合は、それをクローンする。
終わったら、expoプロジェクト内に移動して、.gitフォルダを削除する。
# / $ cd packages # /packages/ $ expo init # もしくは $ git clone git@github.com:username/expo-project.git $ cd ./expo-project # /packages/expo-project/ $ rm -rf .git
package.jsonに、nameとversionフィールドを追加する。
# packages/expo-project/package.json { "name": "expo-project", "version": "0.0.0", ... }
expoのプロジェクトをmonorepoに対応させるために、expo-yarn-workspacesパッケージをインストールする。
# /packages/expo-project $ yarn install $ yarn add --dev expo-yarn-workspaces
package.jsonにpostinstall
スクリプトを追記する。
同時に、mainの内容を書き換え、expo-yarn-workspacesの設定も追記する。
# /packages/expo-project/package.json { ... "main": "__generated__/AppEntry.js", "scripts": { "start": "expo start --clear", ... "postinstall": "expo-yarn-workspaces postinstall" }, ... "expo-yarn-workspaces": { "symlinks": ["expo-modules-core"] } }
metro.config.jsを作成する。
# /packages/expo-project/metro.config.js const { createMetroConfiguration } = require('expo-yarn-workspaces'); module.exports = createMetroConfiguration(__dirname);
実際にyarn run start
を実行してみて動くことを確認する。
動かない場合は、metro.config.jsがあるか、package.json内のmainが、___generated___/AppEntry.js
を指しているか等を確認する。
Firebase プロジェクト
ルートディレクトリ内で、Firebaseプロジェクトを作成する。 すでにリモートリポジトリがある場合は、それをクローンする。
# / npm install -g firebase-tools firebase login firebase init ## もしくは git clone git@github.com:username/firebase-project.git cd firebase-project # /firebase-project rm -rf .git cd ../
packages
配下にfunctionsフォルダを移動する。
リモートリポジトリをクローンした場合は、設定ファイルをルートディレクトリに移動させる。
# / mv functions packages ## もしくは mv firebase-project/functions packages ### 設定ファイルをルートディレクトリに移動させる。 mv firebase-project/.firebaserc .firebaserc mv firebase-project/firebase.json firebase.json mv firebase-project/firestore.indexes.json firestore.indexes.json mv firebase-project/firestore.rules firestore.rules mv firebase-project/storage.rules storage.rules
firebase.json
を編集する。
functions
の設定にsource
フィールドを追加して、現在のfunctions
のパスを指定する。
# /firebase.json { "functions": { "source": "packages/functions" } }
packages/functions
内に移動して、tsconfig.json
を編集する。
具体的には、typeRoots
の中身を修正してルートディレクトリにあるnode_modules/@types
を参照するに設定する。
/packages/functions/tsconfig.json { "compilerOptions": { ... "typeRoots": ["./types", "../../node_modules/@types"], }, }
functions
のpackage.json
に、name
フィールドとversion
フィールドを加える。
# /packages/functions/package.json { "name": "functions", "version": "0.0.0", ... }
packages/functions
内で、yarn install
を実行する。そしてビルドを実行する。
# / $ cd packages/functions # /packages/functions/ $ yarn install $ yarn build
最後に、デプロイできることを確認する
# /packages/functions/ $ firebase deploy --only functions
おわりに
いままでも、Lernaを使ってぐちゃぐちゃになっているexpo関連のプロジェクトをまとめてしまって、monorepoとして管理しようと試みたことはあった。 ただそのたびに、忙しい等の言い訳をして避けてきていたので、今回心にゆとりがあったこともあり、挑戦してみた。
実際にやってみると、思っていたほどむずかしいことはほとんどなかった。 煩雑だった複数プロジェクトの管理は楽になるし、GitHub Actionsの設定も特段変更する必要はほとんどなかったので、いいことづくめだということがわかった。
よかったよかった。
参考にした記事
expo/packages/expo-yarn-workspaces at master · expo/expo · GitHub
GitHub - lerna/lerna: A tool for managing JavaScript projects with multiple packages.
LernaとYarn WorkspacesでMonorepo管理 - Cybozu Inside Out | サイボウズエンジニアのブログ
git - Can you have additional .gitignore per directory within a single repo? - Stack Overflow
Structuring a Firebase web project with Lerna | by João Teixeira | Firelayer | Medium