はじめに
ある程度の規模のプロジェクトになってくると、以下のような悩みが出てきたりするんじゃないでしょうか?
- ビルド時間が長い
- どこに何があるのかわからない
- プロジェクトによって設定や環境が異なり、セットアップに時間がかかる
今回はこういった問題を解消してくれるNxというツールを使いましょうと言う話
Nxの概要について触れたのち、プロジェクト初期のおすすめの構成についても書けたらと思います。
大規模プロジェクト用でしょと思われるかもしれませんが、僕は割と小規模~中規模プロジェクトにこそNxは輝くんじゃないかなと思ってます。
Nx概要
ざっくり言うと、モノレポをベースとしたビルドシステムです。
そもそもモノレポがどういったものか知らない方もいらっしゃると思うのでまずはモノレポについて話した後Nxのメリットについて触れていきます。
モノレポとは?
複数の役割を持ったコードを一つのリポジトリで管理することです。
Googleは一つのリポジトリで全てのプロジェクトを管理しているみたいな話を聞いた方もいらっしゃるかと思いますが、他の有名なIT企業(UberやMetaなど)も採用していると言われていたりします。
代表的なメリットに
- 依存関係やプロジェクトの全体像を把握しやすい
- コードの共通化ができる
- ツールの標準化がしやすい
などがあったりします。
この辺りの話はNxのメリットにもつながってくる話なので、先に進めようと思います。
Nxメリット
改めてですがNxはモノレポをベースとしたビルドシステムです。
つまり、プロジェクトを一つのリポジトリで完結しつつ、ビルドなどのエコシステムを管理してくれるツールです。
代表的な機能をリストアップしておきます
モノレポ管理
Nxではモノレポの管理方法に2つのオプションを用意しています。
- Package-Based Repos
- Integrated Repos
1つめのPackage-Basedというのは他のモノレポツールに多い、各パッケージに対してpackage.json
を持ち、workspaceを用いて管理されるリポジトリです。
以下のような形に管理され、基本的には自分達でパッケージ群をメンテナンスする必要があるモードです。
この場合、Nxがサポートしてくれるのはプロジェクトの依存関係の可視化やキャッシュによるビルドの効率化のみになります。
myorg/
├── packages/
│ └── is-even/
│ ├── index.ts
│ └── package.json
├── nx.json
└── package.json
2つめのIntegratedというのは、プロジェクトに1つのみpackage.json
を持ち、Nxのルールに従ってパッケージを管理していくモードです。
一定、Nxのルールに従う必要があったり、パッケージを一括で全てあげないといけないみたいな制約はあるものの、テストやlint、ビルドなどもトータルにサポートしてくれるので、こちらが推奨になってます。
myorg/
packages/
└── is-even/
├── src/
| └── lib/
| | ├── is-even.spec.ts
| | ├── is-even.ts
| └── index.ts
├── project.json
├── package.json
├── ...
└── tsconfig.json
├── tools/
├── nx.json
├── package.json
├── README.md
└── tsconfig.base.json
Next.jsやNest.jsをTypeScriptでサポート
Nxではパッケージの管理だけでなく、プラグインが非常に優秀で、Next.jsやNest.jsについてもサポートしてくれます。
Nxプロジェクトを作成後、Next.jsのプラグインを追加し、アプリケーションを作成します
yarn add --dev @nrwl/next
nx g @nrwl/next:app my-new-app
すると、apps/
というディレクトリにNext.jsのアプリケーションが生成されます
TypeScriptも標準サポートされてますし、tsconfigやeslintなどはルートディレクトリにあるbaseファイルを継承した形で作られるため、管理がとても楽になります。
myorg
├── apps/
└── my-new-app/
├── pages/
├── components/
├── next.config.js
└── tsconfig.json
├── packages/
├── tools/
├── nx.json
├── package.json
├── README.md
└── tsconfig.base.json
エコシステムのサポート
NxのサポートはNext.jsなどのフレームワークに留まりません。
E2EテストやStorybookについてもプラグインでサポートしています。
例えば、先ほど作ったNext.jsのアプリケーションに対し、Storybookを追加したい場合、
yarn add --dev @nrwl/storybook
nx g @nrwl/storybook:configuration my-new-app
とすればそれだけでStorybookを使える状態になります。
他にも、ESLintやPrettierなどについても標準サポートで、プロジェクト全体で同じものが使えるというのはとても良いですね
ビルド・Lintなどの高速化
何よりも協力な機能ですが、Nxではキャッシュが非常に優秀で、差分のある部分のみを再ビルドしてくれたりします。
Nxでは各機能をマイクロサービスのようにサービスレベルで切り出したりするので、差分のある部分のみをビルドしてくれるというのはかなり協力になってきます。
Nx Cloudというクラウドサービスを併用すれば、クラウドキャッシュを用いることも可能です。
複数人による開発時やCI、リリースの高速化に最適です
Nxのデメリット
もちろんデメリットも存在するので軽く触れておきます。ズバリ1つ。
パッケージのアップデートがNxに依存するということです。
Nxのmigrateとともにバージョンを上げる形になります。(ただし、対応はめちゃくちゃ早いので特に気にならないと思います)
こんな構成にしてみると良さそう
さて、色々語り過ぎてしまいましたが、僕がNxを2年近く使っていてこういう構成にすると良いと思う。と言う話をしようと思います。
プロジェクトの初期をイメージしています。
プロジェクトがより大規模になれば変えないといけないところはあると思います
簡単なECサイト
apps/web
Next.jsによるアプリケーション
細かなレイアウトの調整や各ライブラリとの繋ぎこみを行う
libs/auth、libs/chat、libs/product
機能ごとに切られたReactのライブラリ
マイクロサービスのように各サービスには依存しないコードになっている
役割が閉じているのであれば、データフェッチを行なったりビジネスロジックが入ったりしているのはOK
libs/shared
各アプリやライブラリで共通で使用するコード群
libs/shared/ui
→ 俗に言うatomsに近いものが入っている
libs/shared/hooks
→ どのようなアプリケーションから呼ばれてもいいようなhooks。react-useみたいなもの
libs/shared/utils
→ 外部ライブラリにしても良さそうなutil関数等
まとめ
いかがでしたでしょうか?
大半がNxの紹介みたいになってしまいましたが、プロジェクトの初期から入れるのであれば小規模~中規模のプロジェクトであったとしてもNxによるモノレポを勧めたいなと思っております。
Turborepoなど新しいモノレポツールもあり、迷いどころではありますが、Nxは強力なエコシステムのサポートとキャッシュ効率化によるビルドの高速化が非常に優秀だなと思います。
新しいプロジェクトを始める時にはぜひ参考にしてみてください