[Flutter]pub workspaceを使って脱melosしてみた
はじめに
こんにちは、株式会社SHIFT アプリケーション開発テクノロジーグループでFlutterアプリ開発をしている大矢です。
monorepo構成のプロジェクトをmelosを用いて管理していましたが、先日リリースされたpub workspaceに移行しました。そのサンプルを公開いたします。
pub workspaceはFlutter 3.27.0以降で使えるようになった、単一のリポジトリで複数のアプリ、パッケージを開発するmonorepo構成を行うための機能です。
同様のツールとしてサードパーティのmelosが一般的ですが、せっかく標準の機能として似たようなものがリリースされたので、使ってみたいというモチベーションです。
当記事で説明すること
pub workspaceの導入
melosの削除
当記事で説明しないこと
Flutter 3.27.0へのアップグレード手順
melosの導入手順
SDKバージョンを3.27.0以上に上げる
上げる前のバージョンによってやることが変わる可能性があるので詳細は割愛しますが、pub workspaceを使うためにSDKバージョンを3.27.0以上に上げる必要があります。
詳細は適宜バージョンアップを解説している記事やFlutterのドキュメントを参照ください。
melosからworkspaceに置き換え
melos削除
まず、melosによって自動的に作成されているpubspec_overrides.yamlを削除するため、以下を実行します。
melos clean
次にリポジトリルートのpubspec.yamlを変更して、melosの依存を削除します。
dev_dependencies:
melos: # <- 削除
もし、もうmelosを使わないのであれば、パッケージを無効化しておきます。
dart pub global deactivate melos
melos.yamlは後述の乗換え先を作るときに参照するため、一旦置いておきます。
pub workspace導入
workspaceを導入していく流れは公式のドキュメントに従います。 https://dart.dev/tools/pub/workspaces
リポジトリルートのpubspec.yamlに以下を追記します。
workspace:
- packages/package1
- packages/package2
- ...
melosで管理していた時は、おそらくエントリポイントとなるアプリはapps/app等、その他のパッケージはpackages/パッケージ名等のディレクトリで構成している方が多いのではと思います。(少なくとも私はそうでした)
pub workspaceの例に従うとpackages/パッケージ名に統一することになりますが、特に制約があるわけではないので、アプリは従来通りapps/app等に置いても問題はありません。
次に、各アプリ・パッケージのpubspec.yamlに以下の行を追加します。
environment:
sdk: ^3.6.0
flutter: ">=1.17.0"
resolution: workspace # <- これを追加
そして、パッケージをインポートする側のpubspec.yamlに適宜dependenciesタグを書きます。
なお、pathタグは原則省略可能 です。同名パッケージがpub.dev上にある場合は少し例外があるのでドキュメントも参照ください。
dependencies:
package2:
path: ../package2
あとは、リポジトリ配下の任意の場所でflutter pub getすれば、各パッケージ内のpubspec.lockが削除され、リポジトリルートに全ての依存が書かれたpubspec.lockができるはずです。
melos.yamlのscriptsの代替
melosコマンド経由でよく使うコマンドを実行できるマクロ機能ですが、現状、pub workspaceではここに少し課題があるように見受けられます。この点は割り切って使うことを推奨します。
pub workspaceにはmelos.yamlのscriptsを直接代替するようなマクロ機能はありません。
ドキュメントによるとflutter pubコマンドでは-Cで対象パッケージを個別に指定できる機能があるのみです。
# pub workspaceドキュメントから例を拝借
dart pub -C packages/client_package publish
# Same as
cd packages/client_package ; dart pub publish ; cd -
ちなみに、flutter cleanやflutter analyzeなどはworkspaceを導入することでpub get同様全パッケージに対して動作するため、特に対応は不要でした。
もしかすると今後のアップデートでまた変わっていくかもしれませんが、一旦私は以下のように対応しました。
(従来、以下はいずれもmelos.yamlにマクロを用意して使っていました。)
build_runnerを実行するマクロ -> Makefileに置き換え
testを実行するマクロ -> IDE(私はVSCode)のマクロ実行機能に置き換え
その他flutter pubコマンド系など自動的に全体化されたものはマクロ使用を廃止
build_runner実行をMakefileで書く場合は、一例として以下のようになると思います。
PACKAGE1 = packages/package1
PACKAGE2 = packages/package2
build_runner = dart run build_runner build --delete-conflicting-outputs
build:
cd $(PACKAGE1) && $(build_runner)
cd $(CURDIR)/$(PACKAGE2) && $(build_runner)
まとめ
以上、先日リリースされたばかりのpub workspaceを早速使ってみました。
今回少しですが触ってみて、現状melosと比べて以下のようなメリットデメリットがあると感じました。
メリット
dependenciesにリポジトリ内パッケージを追加する際、pathタグを書かずに済む。
flutterの標準的なコマンドのいくつかが、リポジトリ内の全パッケージに対して実行できるようになる。
melos.yamlやpubspec_overrides.yamlを使わずに済む、または使う量を減らせるため、設定ファイルが減りリポジトリが整理しやすくなる。
デメリット
melos.yamlのscriptsでマクロを組んでいる場合、同等機能がなくかえって不便になってしまう可能性がある。
issueは色々と上がっている ため、すぐにプロダクションへ導入することは慎重に検討すべきですが、将来的には実用に耐える機能になっていくと思います。
お問合せはお気軽に
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/
PHOTO:UnsplashのShubham Dhage