これはHubble Advent Calendar 2025の 22 日目の記事です。
昨日は @kyohei-0xcc さんでした。
はじめに
こんにちは、株式会社 Hubble のフロントエンドを担当している @KOHETs です。
Hubble ではフロントエンドの開発基盤として Nx を採用し、Angular を中心としたモノレポ構成で開発を行っています。
Nx といえば、CI/CD の高速化などが注目されがちですが、他にも素晴らしい機能があります。
その一つが Nx Generator です。
今回は、Nx Generator を単なる「ボイラープレート(雛形)作成ツール」としてだけではなく、マイグレーションツールとしてどのように活用しているかを紹介します。
定型作業の自動化を超えて
Nx Generator は、ファイル生成やコードの書き換えを自動化するためのツールです。Angular を使っている方であれば、ng generate や ng update の裏側で動いている Schematics とほぼ同じもの(Nx はこれをラップして拡張したもの)です。
日常的な開発では、以下のようなコマンドを使うことが多いと思います。
nx g @nx/angular:component my-component
これは、「新しいコンポーネントを作る」というタスクを効率化する、いわば「定型作業の自動化」です。これだけでも十分に便利で、チーム内でのディレクトリ構造や命名規則の統一に役立ちます。
しかし、Hubble における Generator の活用はこれだけではありません。
設定管理とメンテナンスの自動化
長く運用されているプロダクトでは、設定ファイルの更新や組織的なルールの適用が必要になります。
Hubble では現在、200 以上のプロジェクトがモノレポ内に存在しており、それら全ての設定(project.json、.eslintrc.json、jest.config.tsなど)を手作業でメンテナンスするのは大変です。
レビューで毎回細かい設定漏れを指摘するのは難しく、どうしても見落としが発生してしまいます。
実践:Angular Control Flow への段階的移行とルール化
例えば、Angular v17 から導入された Control Flow (@if, @for など) への移行を例に挙げます。
Angular 公式からも移行用の Schematic (@angular/core:control-flow) が提供されていますが、移行だけだと翌週にはまた *ngIf が混入してしまう可能性があります。
Lint ルールもプロジェクトに追加することで古いコードの再混入を防げるため、公式 Schematic をラップし、「変換処理」と「Lint ルールの追加」をセットで実行できるカスタム Generator を作成しました。
変更のコード化
// tools/generators/control-flow-migration/generator.ts
export async function controlFlowMigrationGenerator(
tree: Tree,
options: ControlFlowMigrationGeneratorSchema
) {
// Angular公式のSchematicを実行してコードを変換
// Nxのラップ関数を使えば、公式Schematicもただの関数として呼び出せる
const controlFlow = wrapAngularDevkitSchematic(
"@angular/core",
"control-flow"
);
await controlFlow(tree, { format: true, path: options.directory });
// 変換が終わった箇所に対して、即座にLintルールを追加する
await angularEslintTemplateRuleMigrationGenerator(tree, {
...options,
rule: "@angular-eslint/template/prefer-control-flow",
// 既存プロジェクトは変換漏れなども考慮して、一旦 warn を設定
severity: "warn",
});
}
// tools/generators/angular-eslint-template-rule-migration/generator.ts
export async function angularEslintTemplateRuleMigrationGenerator(
tree: Tree,
options: Schema
) {
// 指定ディレクトリ以下の .eslintrc.json を探索
visitNotIgnoredFiles(tree, options.directory, (filePath) => {
if (!filePath.endsWith(".eslintrc.json")) {
return;
}
// 実際にルールを追加
addAngularEslintTemplateRuleToJson(
tree,
filePath,
options.rule,
options.severity
);
});
await formatFiles(tree);
}
このように実装すると、以下のようなメリットがあります。
- 確実性: 移行と同時に Lint ルールが適用されるため、古い書き方の再混入を防げます。
- 影響範囲の制御: ルートレベルの設定ではなく各プロジェクトの設定ファイルを変更するため、他のプロジェクトに影響を与えず、段階的に移行できます。
- テスト: Generator 自体のユニットテストを書くことで、意図しない破壊的変更を防げます。
新規プロジェクトへの適用
このロジック(特に Lint ルールの追加)を新規プロジェクト作成時にも適用できるようにすると、さらに便利です。
// tools/generators/new-lib/index.ts
import { libraryGenerator } from "@nx/angular/generators";
import { angularEslintTemplateRuleMigrationGenerator } from "../angular-eslint-template-rule-migration";
export default async function (tree: Tree, schema: any) {
// 1. 普通にライブラリを作る
await libraryGenerator(tree, { name: schema.name });
// 2. Control Flowを強制するLintルールを最初から適用
await angularEslintTemplateRuleMigrationGenerator(tree, {
directory: libsDir(schema.name),
rule: "@angular-eslint/template/prefer-control-flow",
// 新規ライブラリは最初から error を設定
severity: "error",
});
}
これにより、新しく作られるコードは最初から「最新のルール」が適用された状態で生まれてきます。
なぜ Generator なのか
最近では GitHub Copilot や ChatGPT、Claude などの AI ツールが非常に優秀になり、「これ書き換えて」と指示すれば、それらしいコードを一瞬で生成してくれます。マイグレーションも任せても良いかもしれません。
Hubble では、あえてコストをかけて Generator を書いています。
理由は、AI は確率的(Probabilistic)であり、Generator は決定論的(Deterministic)だからです。
AI は確率的で、100 ファイルに対して実行した時、99 ファイルは正解でも 1 ファイルだけ微妙に違う修正をする可能性があります。一方、Generator は決定論的で、100 ファイル全てが同じロジックで変更されることが保証されます。また、Generator 自体のユニットテストを書くことで、意図しない破壊的変更を防げます。
CI/CD パイプラインの設定や、ビルド構成、Linter のルールなど、「1 つのミスが全体に影響する」ようなインフラに近いコードについては、AI に頼り切るのではなく、Generator という形で再現可能なロジックとして管理するのが良いでしょう。
Generator を書く文化の効果
機能を継続的に開発していく上で、設定は徐々にカスタマイズされていくものです。
しかし、属人的な管理や手作業が必要になると、そのカスタマイズはしづらくなってしまいます。
今後も継続的に安全に効率的に開発をするため、Generator を書く文化があれば、「Generator 書けば一瞬で終わるし、テストもあるから安全だよね」というマインドセットで、設定のカスタマイズも気軽に行えるようになります。
まとめ
Nx Generator は、単なるコード生成ツールとしてだけでなく、チームの知識やルールをコード化し、自動化するためのフレームワークとしても活用できます。
Hubble では、こうした開発基盤への投資を惜しまず、開発者が本質的な価値提供に集中できる環境作りを続けています。
最初は Generator を書くコストが高く感じるかもしれませんが、長期的に見れば、レビューコストの削減や品質の安定化など、十分なリターンが得られるはずです。
皆さんのチームでも、Generator を活用してみると良いかもしれません。
明日の Hubble Advent Calendar 2025 は、 @power3812 です。お楽しみに!