4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

git submodule + yarn workspace を使ったライブラリ運用

Last updated at Posted at 2021-05-08

この記事の対象読者

  • モノリポを複数運用することにしたが、一部のコードをライブラリとしてモノリポ間で共有したい(Googleみたいに一つのリポジトリに入れるのは嫌という人)
  • 依存しているNPMパッケージにバグがあり、PRを出しつつ直したバージョンを使いたい
  • プライベートリポジトリで作っているコードの一部を、ライブラリとしてパブリックなリポジトリで公開したい

と、グダグダ書きましたが要は ↓ のような状況を上手に扱うにはどのようにすればいいかを説明していきます。

扱いたい状況.png

Git Submodule

Git Submoduleは、あるリポジトリの中で別のリポジトリを参照し、管理するためのツールです。

今回なら、モノリポにライブラリのリポジトリを追加し、管理するために使います。

この記事で細かくGit submoduleについて説明するつもりはないので、詳しく知りたい方は公式ドキュメントを参照してください。

Yarn Workspace(あるいはnpm workspaces/pnpm workspaces)

Yarn Workspaceは、Yarnを使ってモノリポを運用するためのツールです。

例えば、

  • app/package.json
  • lib1/package.json
  • package.json

というような構造があったときに、appの中のコードでrequire('lib1')などということができるようになります。

こちらも詳しく説明するつもりはないので、公式ドキュメントへのリンクを掲載しておきます。

実際にやってみる

今回は、下記のリポジトリを用いて説明していくことにします。

  1. submodule (submoduleはライブラリ用のリポジトリでRollupのテンプレート1を使って用意しました。)
  2. monorepo1

まずmonorepo1の中でsubmoduleを利用するには、monorepo1のリポジトリでgit submodule addを実行します。

git submodule add https://github.com/coder-ka/submodule

この操作により、

  • submodule フォルダ
  • .gitmodules ファイル

が追加されます。

.gitmodules の中をのぞくと

[submodule "submodule"]
	path = submodule
	url = https://github.com/coder-ka/submodule

となっており、"submodule"というリポジトリがsubmoduleとしてsubmodule/ディレクトリで管理されているということがわかります。(名前がややこしくてすいません)

ここで、submoduleの中のpackage.jsonの"name"キーを@coder-ka/submoduleに変更しておいてください。(これによりrequire('@coder-ka/submodule')となる)

つぎは、Yarn Workspaceです。

まずリポジトリルートで初期化を行います。

yarn init -y

そして、生成したpackage.jsonの内容を変更します。

{
  "private": true,
  "workspaces": [
    "app",
    "submodule"
  ]
}

このpackage.jsonはWorkspace管理のためのものなので"private" :trueが必須になっています。(NPMリポジトリで公開しないため)

また、"workspaces"にはモノリポ内のリポジトリとして扱うフォルダのパスを配列で指定します。(packages/*みたいな指定の仕方もできますが、今回は割愛)

submoduleは先ほど追加したので存在しますが、appフォルダがないので作ります。

mkdir app

# ついでに初期化
cd app
yarn init -y

また、リポジトリ内であればどこでもいいので yarn コマンドを実行しておきます。

yarn

これにより、各ワークスペースが依存するパッケージがインストールされ、リポジトリのルートフォルダにnode_modules/が配置されます。(さらにnode_modules/@coder-ka/submodule/submodule/ へのSymlinkなので、ライブラリへの変更が即座に反映される)

次に app/index.js を作成し、コードを書きます。

index.js
const howLongTillLunch = require('@coder-ka/submodule')

console.log('it will be lunchtime in ' + howLongTillLunch());

そして、今回に限っては使っているテンプレートの都合でRollupによるビルドを行う必要がありますが、これは本質的な内容ではないのであまり気にしないでください。

# submodule/フォルダで yarn build しているのと同じ
yarn workspace @coder-ka/submodule build

これで app/index.js が正常に動くようになるので、

node app/index.js

とすれば、it will be lunchtime in 18 hours とコンソールに出てきます。

これで無事に別リポジトリで管理しているライブラリを別のモノリポ内で動かすことができました。

懸念点と解決策

考えられる懸念点と解決策について書いていきます。

複数のモノリポからの依存

複数のモノリポからライブラリのリポジトリが参照される構成になると、ライブラリへの変更によるほかのモノリポに対する影響が気になってきます。

そんな時は、下記のような運用が良いと思われます。

例えば、

  • submodule
  • monorepo1
  • monorepo2

がある場合は、submoduleのリポジトリにmonorepo1/monorepo2のブランチを作成し、それぞれのモジュールの変更はそのブランチに反映させるようにします。

Git Submoduleはデフォルトではmasterを参照するので、.gitmodulesbranchを追加します。

[submodule "submodule"]
	path = submodule
	url = https://github.com/coder-ka/submodule
	branch = monorepo1

これで git submodule update --remote(サブモジュールの更新) をしたときにmonorepo1の内容を参照してくれます。

master には monorepo1 での運用で動作が安定していることが確認できた後に反映すれば、monorepo2 はそれを取り込むことができます。(もちろん、直接 monorepo1 から取り込むこともできます)

終わりに

Git Submodule + Yarn Workspace の組み合わせが有用であることが理解いただけたでしょうか?

今までは、公開や変更の手間などを気にしてライブラリを別リポジトリで作ることを躊躇していた方もいるかもしれませんが、この方法なら無理なくライブラリを運用かつ利用していくことができます。

ライブラリとして公開できる汎用性を持ったコードを作ることは、それにかかわるコミュニティをどんどん便利なものにしていってくれます。

是非この運用法を活用して、生産性向上に役立てていただければと思います。

  1. Rollup公式のTypeScriptのUMDライブラリのテンプレートにava(テストフレームワーク)を私が追加したもの

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?