Nxを極めるハイスケールなフロントエンド開発を加速する実践テクニックのトップ画像

Nxを極めるハイスケールなフロントエンド開発を加速する実践テクニック

投稿日時:2025/04/07 23:30
新福 宜侑のアイコン

ファインディ株式会社 / フロントエンドテックリード

新福 宜侑

Xアカウントリンク

Nxとは

Nxは、Nrwlが開発しているOSSのモノレポ管理ツールです。

ファインディではフロントエンドのリポジトリにNxを採用しており、CIの高速化に活用しています。

この記事ではNxを活用して、スケールするソフトウェア開発に柔軟に対応しつつ、高速な開発を実現するテクニックを紹介します。

Nxを選ぶ理由

モノレポ管理ツールには、Nx以外にもLernaTurborepoなどがあります。

ファインディでは、アプリケーション開発に有用な機能が豊富であったことや継続的なメンテナンスが見込めること、個人的に導入実績があったことなどからNxを採用しました。

2025年現在、Nxを選ぶ理由は何でしょうか?改めて振り返ろうと思います。

理由1:変更検知

アプリケーションのコードベースが増えると、CIでの実行時間も伸びます。

Nxにはモノレポ内のプロジェクトの依存関係を自動的に検知し、コードの変更に対して依存関係のあるプロジェクトのみビルドやテストを実行する機能があります。

https://nx.dev/ci/features/affected

必要なタスクのみ実行されるため、CIの高速化が狙えます。

GitHub Actionsでの活用例を次に示します。

steps:
  - uses: actions/checkout@v4
    with:
      fetch-depth: 0  # nx affected の実行に必須
      filter: tree:0  # チェックアウトの高速化が見込めます
(中略)
  - uses: nrwl/nx-set-shas@v4
  - run: npx nx affected --target=build,test,lint

fetch-depth: 0 を利用するとチェックアウト時間が延びやすいですが、filter オプションを組み合わせることで短縮が可能です。

理由2:キャッシュ

Nxには実行されたタスクをキャッシュし、同じタスクの再実行を回避する仕組みがあります。

https://nx.dev/ci/features/remote-cache

ローカルキャッシュに加え、リモートキャッシュの機能も備えており、前述の変更検知機能と併用することでCIの大幅な高速化が実現できます。

https://nx.dev/nx-cloud

理由3:依存関係の制御

モノレポで開発していると、モノレポ内のプロジェクト同士の依存関係が複雑になっていきます。

Nxは標準で搭載されているESLintルールにより、循環参照や意図しないモジュールへの依存を防止できます。

https://nx.dev/features/enforce-module-boundaries

モノレポ管理のための実用的な機能が揃っているのもNxを選ぶ理由の一つとなるでしょう。

理由4:エコシステム

NxにはAngular、React、Vue.jsといったフロントエンドのメジャーなフレームワーク用の公式プラグインが提供されています。

https://nx.dev/plugin-registry

Nxの更新の際には nx migrate コマンドを実行することで、対応するフレームワークのバージョンアップやコードのマイグレーションが自動的に行われます。

https://nx.dev/nx-api/nx/documents/migrate#migrate

コミュニティも活発であり、サードパーティ製のプラグインやNxを用いた開発の知見が豊富です。

https://nx.dev/community

理由5:Distribute Task Execution (DTE)

NxにはCIで実行するタスクを複数のリモートマシンに分散させる機能があります。

https://nx.dev/ci/features/distribute-task-execution

よくあるCI高速化の手法では、ビルドやテストといったタスクの種類で並列化しますが、CIにかかる時間は一番遅いタスクに左右されます。

DTEでは、どのマシンにどのタスクを割り振るかをNxが判断し効率的に並列化します。

DTEの動作イメージ
DTEの動作イメージ(Nx公式ドキュメントより)

CI高速化の手法としてDTEは非常に興味深く、従来の方法では頭打ちとなるような場合でも更なる高速化を見込めます。

Nxの機能活用

Nxは変更検知やキャッシュ機能などモノレポ管理ツールとして便利な機能を持っていますが、Nxのユニークな点はそれ以外にもあります。

コードジェネレーター

Nxは nx generate コマンドでコードを生成できます。

コードジェネレーターは公式で提供されているものの他に自作することもできます。

https://nx.dev/extending-nx/recipes/composing-generators#composing-generators

import type { Tree } from '@nx/devkit';
import { libraryGenerator } from '@nx/js';

type Schema = {
  name: string;
};

export default async function (tree: Tree, schema: Schema) {
  await libraryGenerator(
    tree,
    { name: schema.name }
  );
}

ファインディでは、CRUD単位で画面を実装するのにNxのコードジェネレーターを活用しています。

NxのGeneratorを活用した管理画面200ページのリニューアル事例 - Findy Tech Blog

コードジェネレーター用のテストユーティリティも完備されているため、作りっぱなしになることが起きづらく、「気付けば誰も使っていなかった」というようなことも防げるでしょう。

@nx/devkit

Nxはモノレポ内のプロジェクトの追加・削除の状態や依存関係を「プロジェクトグラフ」として保持しています。

プロジェクトグラフを使った設定の自動化もNxの大きな特徴です。

次のコードは @nx/devkit を使ってStorybookの設定を自動化する例です。

// apps/example-app/.storybook/main.js
import { createProjectGraphAsync } from '@nx/devkit';

const getStories = async () => {
  const graph = await createProjectGraphAsync();

  // Storybookが不要なプロジェクトは無視
  const ignoredProjects = ['example-e2e', 'example-utils'];

  // 特定のメタ情報が含まれるプロジェクトのStorybook
  return Object.keys(graph.nodes)
    .filter((key) => graph.nodes[key].data.tags?.includes('scope:example-app'))
    .filter((key) => !ignoredProjects.includes(key))
    .map((key) => {
      const project = graph.nodes[key].data;
      return {
        titlePrefix: project.name,
        directory: `../../../${project.sourceRoot}`,
      };
    });
};

const config = {
  addons: ['@storybook/addon-essentials'],
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },
  stories: getStories(), // Nxの機能で自動登録される
};

export default config;

Nx Console

Nx Consoleは公式のエディタ拡張です。Nxのコマンドを実行するためのGUIやプロジェクトの依存関係の可視化などができます。

https://github.com/nrwl/nx-console

直近のアップデートにより、Copilot ChatなどAIアシスタントとの連携ができるようになりました。

https://nx.dev/features/enhance-AI

モノレポのコンテキストを理解した上でコードの提案などを行ってくれるため、開発効率の向上が期待できます。

Nx Agentsで実現する次世代のCI

Nxの特徴的な機能の一つにDTEがあります。

Nx Cloudではリモートキャッシュ機能の他にも、DTEのマネージドサービスとして「Nx Agents」が提供されています。

https://nx.dev/ci/features/distribute-task-execution

DTE用のCIを自分で構成することもできますが、設定が複雑であったり、CIの再実行の手順を間違えやすいというデメリットを考慮する必要があるため、Nx Agentsの利用をおすすめします。

ファインディでは去年から導入しており、CIの高速化を実現しました。

https://tech.findy.co.jp/entry/2024/10/28/070000

また、Nx Agentsの直近のアップデートで「Assignment rules」という機能が追加されました。

https://nx.dev/ci/reference/assignment-rules

Assignment rulesを使うと、DTEで実行されるタスクを特定のマシンに割り振ったり、タスクの並列実行数をマシンスペックに合わせて変更したりできます。

設定の例を以下に示します。

distribute-on:
  00-changeset-s: 3 custom-linux-medium-js
  01-changeset-m: 3 custom-linux-medium-js, 2 custom-linux-large-js
  02-changeset-l: 4 custom-linux-medium-js, 4 custom-linux-large-js
  # changesetは任意の数を定義できます
  # マシンスペックは https://nx.dev/pricing#resource-classes 参照

assignment-rules:
  - projects:
      - sample-app
    targets:
      - build*  # ワイルドカード指定も可能
      - typecheck
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 1  # 並列実行数を絞ってメモリ不足を回避
      - agent: custom-linux-large-js
        parallelism: 3  # 高スペックなマシンでは並列実行数を上げて高速化

  - targets:
      - build
      - test
      - typecheck
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 2
      - agent: custom-linux-large-js
        parallelism: 4

  - targets:
      - lint
      - stylelint
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 6
      - agent: custom-linux-large-js
        parallelism: 8

これまでのNx Agentsでは、タスクとマシンスペックの紐づけができず、重たいタスクの実行時にメモリ不足を起こしてCIが停止してしまうという問題がありました。

Assignment rulesの登場により、メモリ不足を回避しやすくなり、無駄にマシンスペックを引き上げなくても良くなったことでコストパフォーマンスが向上しました。

Assignment rulesについては、弊社のテックブログでも紹介しておりますので是非ご覧ください。 https://tech.findy.co.jp/entry/2025/03/31/070000

まとめ

Nxは単なるモノレポ管理ツールに留まらず、日々の開発に役立つ仕組みをいくつも備えています。

特にCIにおいては、変更検知とリモートキャッシュ、DTEの組み合わせによって、非常に高速かつ将来的なスケールにも耐えうるCIを構築することが可能です。

スピードとスケーラビリティの両立を目指す際に、Nxは有力な候補となるでしょう。

個人的にNx Agentsは今年イチオシのサービスです。DTE構築のハードルが下がった今、次世代のCIを体感する良い機会になるかもしれません。

この記事が皆様の参考となれば幸いです。