【フロントエンド】Nxによる効率的な開発環境を目指しましょう

## はじめに

ある程度の規模のプロジェクトになってくると、以下のような悩みが出てきたりするんじゃないでしょうか？

- **ビルド時間が長い**
- **どこに何があるのかわからない**
- **プロジェクトによって設定や環境が異なり、セットアップに時間がかかる**

今回はこういった問題を解消してくれるNxというツールを使いましょうと言う話

Nxの概要について触れたのち、プロジェクト初期のおすすめの構成についても書けたらと思います。

:::note
大規模プロジェクト用でしょと思われるかもしれませんが、僕は割と小規模~中規模プロジェクトにこそNxは輝くんじゃないかなと思ってます。
:::

## Nx概要

ざっくり言うと、**モノレポをベースとしたビルドシステム**です。

そもそもモノレポがどういったものか知らない方もいらっしゃると思うのでまずはモノレポについて話した後Nxのメリットについて触れていきます。

### モノレポとは？

複数の役割を持ったコードを一つのリポジトリで管理することです。

:::note
Googleは一つのリポジトリで全てのプロジェクトを管理しているみたいな話を聞いた方もいらっしゃるかと思いますが、他の有名なIT企業（UberやMetaなど）も採用していると言われていたりします。
:::

代表的なメリットに

- 依存関係やプロジェクトの全体像を把握しやすい
- コードの共通化ができる
- ツールの標準化がしやすい

などがあったりします。
この辺りの話はNxのメリットにもつながってくる話なので、先に進めようと思います。

### Nxメリット

改めてですがNxは**モノレポをベースとしたビルドシステム**です。

つまり、**プロジェクトを一つのリポジトリで完結しつつ、ビルドなどのエコシステムを管理してくれるツール**です。

代表的な機能をリストアップしておきます

#### モノレポ管理

Nxではモノレポの管理方法に2つのオプションを用意しています。

1. Package-Based Repos
1. Integrated Repos

1つめのPackage-Basedというのは他のモノレポツールに多い、各パッケージに対して`package.json`を持ち、workspaceを用いて管理されるリポジトリです。

以下のような形に管理され、基本的には自分達でパッケージ群をメンテナンスする必要があるモードです。
この場合、Nxがサポートしてくれるのは**プロジェクトの依存関係の可視化**や**キャッシュによるビルドの効率化**のみになります。

```txt
myorg/
├── packages/
│   └── is-even/
│       ├── index.ts
│       └── package.json
├── nx.json
└── package.json
```

2つめのIntegratedというのは、プロジェクトに1つのみ`package.json`を持ち、Nxのルールに従ってパッケージを管理していくモードです。
一定、Nxのルールに従う必要があったり、パッケージを一括で全てあげないといけないみたいな制約はあるものの、テストやlint、ビルドなどもトータルにサポートしてくれるので、こちらが推奨になってます。

```txt
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のプラグインを追加し、アプリケーションを作成します

```bash
yarn add --dev @nrwl/next
nx g @nrwl/next:app my-new-app
```
すると、`apps/`というディレクトリにNext.jsのアプリケーションが生成されます
**TypeScriptも標準サポート**されてますし、tsconfigやeslintなどはルートディレクトリにあるbaseファイルを継承した形で作られるため、管理がとても楽になります。

```txt
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を追加したい場合、

```bash
yarn add --dev @nrwl/storybook
nx g @nrwl/storybook:configuration my-new-app
```

とすればそれだけでStorybookを使える状態になります。

:::note
他にも、ESLintやPrettierなどについても標準サポートで、プロジェクト全体で同じものが使えるというのはとても良いですね
:::

#### ビルド・Lintなどの高速化

何よりも協力な機能ですが、Nxではキャッシュが非常に優秀で、差分のある部分のみを再ビルドしてくれたりします。

Nxでは各機能をマイクロサービスのようにサービスレベルで切り出したりするので、差分のある部分のみをビルドしてくれるというのはかなり協力になってきます。

:::note
Nx Cloudというクラウドサービスを併用すれば、クラウドキャッシュを用いることも可能です。
複数人による開発時やCI、リリースの高速化に最適です
:::

### Nxのデメリット

もちろんデメリットも存在するので軽く触れておきます。ズバリ1つ。
**パッケージのアップデートがNxに依存する**ということです。
Nxのmigrateとともにバージョンを上げる形になります。（ただし、対応はめちゃくちゃ早いので特に気にならないと思います）

## こんな構成にしてみると良さそう

さて、色々語り過ぎてしまいましたが、僕がNxを2年近く使っていてこういう構成にすると良いと思う。と言う話をしようと思います。

:::note
プロジェクトの初期をイメージしています。
プロジェクトがより大規模になれば変えないといけないところはあると思います
:::

### 簡単なECサイト

![スクリーンショット 2022-12-03 0.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/fe44c4e7-4344-8bc0-71b8-605ff0e24db8.png)

#### 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は**強力なエコシステムのサポート**と**キャッシュ効率化によるビルドの高速化**が非常に優秀だなと思います。

新しいプロジェクトを始める時にはぜひ参考にしてみてください