Lerna v6 (Lerna + Nx) について解説

システムエンジニアの蛸井です。今回は Lerna についてと Lerna v6 の Nx の機能について解説します。

Lerna とは

Lerna とは monorepo ツールです。

monorepo とは、1つのリポジトリで複数のサービスを管理することを言います。

monorepo のメリットとして、例えば以下のことが挙げられます。

  • リポジトリ内の複数のサービス間でコードを共有できる
  • サービスを横断してのテストができる
  • リリースが管理しやすい
  • サービス毎に共通したルールの lint などのツールを使用できる

Lerna を使用することにより、複数の node パッケージをまとめて管理できます。

lerna bootstrap コマンドを使用することにより、各サービスの package.json を元にパッケージを一括でインストールし、さらに同じ種類・バージョンのパッケージを共通利用できるようになります。

evocateur さんが開発していた Lerna は version 4.0.0 にて開発が停止しましたが、Nx という monorepo ツールを開発している Nrwl 社が開発を引き継ぎ v5, v6 をリリースしました。

Lerna v5 の変更点

Lerna v5 にて Lerna にキャッシュ機能が備わりました。

lerna.json で useNx フラグを有効にすることで Nx と同等の速度になり、リポジトリの設定にもよりますが以前の Lerna と比較して2~10倍のスピードアップが期待できます。

参考:https://blog.nrwl.io/lerna-used-to-walk-now-it-can-fly-eab7a0fe7700

Lerna v6 の変更点

Lerna v6 では、先ほど紹介した useNx がデフォルトで有効になります。

また lerna add-caching を実行することで、Nx の機能の設定を記載する nx.json を生成できます。

nx.json にはスクリプトの依存関係を指定できます。

// nx.json
{
  ...
  "targetDefaults": {
    "build": {
      "dependsOn": ["^build"]
    },
    "dev": {
      "dependsOn": ["^build"]
    }
  }
}

例えば nx.json を上記のように設定すると、build か dev のどちらかのスクリプトを実行した場合に Lerna は依存するすべてのパッケージに対して build を実行します。

また、次の章で解説する cacheableOperations に設定したスクリプトは実行結果がキャッシュされるようになります。

参考:https://blog.nrwl.io/lerna-reborn-whats-new-in-v6-10aec6e9091c

タスクの結果をキャッシュする

// nx.json
{
  ...
  "options": {
    "cacheableOperations": [
      "lint",
      "typecheck",
      "jest"
    ]
  }
}

例えば nx.json を上記のように設定すると、タスクランナーの実行結果 (lerna run lint など) がキャッシュされるようになります。
対象となるスクリプトは cacheableOperations に登録が必要です。

試しに lerna run lint を2度実行してみます。

$ yarn lerna run lint
yarn run v1.22.19
    $ /app/node_modules/.bin/lerna run lint
lerna notice cli v6.5.1

    ✔  backend:lint (17s)
    ✔  frontend:lint (21s)

 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  Lerna (powered by Nx)   Successfully ran target lint for 2 projects (21s)

Done in 24.66s.
$ yarn lerna run lint
yarn run v1.22.19
    $ /app/node_modules/.bin/lerna run lint
lerna notice cli v6.5.1

    ✔  backend:lint  [existing outputs match the cache, left as is]
    ✔  frontend:lint  [existing outputs match the cache, left as is]

 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  Lerna (powered by Nx)   Successfully ran target lint for 2 projects (43ms)

   Nx read the output from the cache instead of running the command for 2 out of 2 tasks.

Done in 2.18s.

1回目の実行では約25秒かかりました。
2回目の実行ではコマンドの実行の代わりにキャッシュを使用した旨のメッセージ Nx read the output from the cache instead of running the command for 2 out of 2 tasks. が表示され、実行時間は約2秒とすぐ完了するようになりました。

Nx はパッケージごとに前回の実行からファイルの差分があるかどうかを確認し、ファイルに変更が無かった場合にキャッシュを使用します。

また、キャッシュはローカルに1週間保存されます。
nx reset コマンドを実行することで、ローカルに保存したキャッシュを削除できます。

注意点として、cacheableOperations には、同じ入力に対して常に同じ結果を出力するスクリプトのみを設定するようにしてください。

また、nx.json に適切な設定を行うことにより、コマンド実行により生成されるファイル (例えば dist ディレクトリの生成など) も即時に実行完了できます。

参考:https://lerna.js.org/docs/features/cache-tasks

nx cloud でキャッシュを共有する

キャッシュは nx cloud を使用することにより複数のマシンに共有できます。

以下を実行するだけでワークスペースを nx cloud に接続できます。

$ npx nx connect-to-nx-cloud
✔ Enable distributed caching to make your CI faster · Yes

>  NX  Generating @nrwl/nx-cloud:init

UPDATE nx.json

 >  NX   Distributed caching via Nx Cloud has been enabled

   In addition to the caching, Nx Cloud provides config-free distributed execution,
   UI for viewing complex runs and GitHub integration. Learn more at https://nx.app

   Your workspace is currently unclaimed. Run details from unclaimed workspaces can be viewed on cloud.nx.app by anyone
   with the link. Claim your workspace at the following link to restrict access.

   https://cloud.nx.app/orgs/workspace-setup?accessToken=ACCESSTOKEN

実行が完了すると nx.json にアクセストークンが追加され、それ以降は nx cloud 上にキャッシュが保存されるようになります。

試しに1度 lerna run lint を実行した後、nx reset コマンドでローカルのキャッシュを削除します。

$ yarn lerna run lint
yarn run v1.22.19
    $ /app/node_modules/.bin/lerna run lint
lerna notice cli v6.5.1

    ✔  backend:lint (22s)
    ✔  frontend:lint (26s)

 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  Lerna (powered by Nx)   Successfully ran target lint for 2 projects (26s)

   View logs and investigate cache misses at https://cloud.nx.app/runs/xxxxxxxxxx

Done in 28.45s.
$ npx nx reset

 >  NX   Resetting the Nx workspace cache and stopping the Nx Daemon.

   This might take a few minutes.

 >  NX   Daemon Server - Stopped

 >  NX   Successfully reset the Nx workspace.

その後、再度 yarn lerna run lint を実行します。

$ yarn lerna run lint
yarn run v1.22.19
    $ /app/node_modules/.bin/lerna run lint
lerna notice cli v6.5.1

    ✔  frontend:lint  [remote cache]
    ✔  backend:lint  [remote cache]

 ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

 >  Lerna (powered by Nx)   Successfully ran target lint for 2 projects (2s)

   Nx read the output from the cache instead of running the command for 2 out of 2 tasks.

   Nx Cloud made it possible to reuse 2 tasks: https://cloud.nx.app/runs/xxxxxxxxxx

Done in 7.31s.

nx cloud に保存されたキャッシュが使用され、タスクがすぐに完了することが確認できました。

また、タスク実行時にログに表示される https://cloud.nx.app/runs/:taskCode にアクセスすることでタスクの実行結果を閲覧できます。

参考:https://lerna.js.org/docs/features/share-your-cache

まとめ

今回は Lerna に新しく追加された Nx の機能について解説しました。

キャッシュをクラウド上に保存して使用することが、無料でこんなに簡単にできることに驚きました。

非常に便利なのでぜひ使ってみてください。