目次

Oxlint + Oxfmtを使うと、コーディング規約を自動チェックに落とし込み、リントとフォーマットの時間を短縮できます。REALITYが報告したモノレポ移行では、インポートのグループ分けと独自のTailwind CSSクラス順序を維持しながら、チェック時間が9.29秒から2.95秒に短縮されました。

要点#

  • リポジトリで使うルールの網羅性とフォーマットの差分を確認してツールを選ぶ。
  • 機械的な規約にはフォーマットと安全な自動修正を使い、禁止パターンには対処方法が明確なリントエラーを使う。
  • フォーマット、リント修正、ツールの変更を、レビューしやすいコミットに分ける。
  • 自動修正をレビューし、型チェックとテストの両方を実行してから取り込む。

互換性で選ぶ#

REALITYは、Reactアプリケーションと共通のデザインシステムを含む、pnpmワークスペースとTurborepoによるモノレポでBiomeとOxcを検証しました。@themeで定義したTailwind CSS v4のユーティリティがあるため、クラスの並べ替えが重要な要件でした。

Biomeは基本的なフォーマットをほぼ再現し、約460ファイルのうち変更は1ファイルだけでした。インポートの並べ替えでは85ファイル、Tailwindクラスの並べ替えでは71ファイルが変わりました。この検証では、Biomeのクラスソーターがプロジェクトのスタイルシートを読み込まず、独自ユーティリティの配置が変わりました。

Oxfmtは、検証した基本的なフォーマットを差分なく再現し、必要なインポートのグループ分けと、スタイルシートを考慮したTailwindの並べ替えにも対応していました。これは特定のリポジトリでの結果です。どちらのツールを選ぶ場合も、次の4点を検証してください。

  • 代表的なファイルでのフォーマット差分。
  • インポートのグループ分け、空行、副作用インポート。
  • cn()やcva()などのヘルパー内にある独自のTailwindユーティリティ。
  • 現在依存しているすべてのESLintルールへの対応状況。

共通のチェックを設定する#

.oxlintrc.jsonと.oxfmtrc.jsonをリポジトリのルートに配置します。REALITYは、パッケージごとのリント・フォーマットタスクを、各ツールをリポジトリ全体に1回ずつ実行する方式に置き換え、ツールの直接依存を14個からoxlint、oxfmt、oxlint-tsgolintの3個に減らしました。

報告されたスクリプトは次のとおりです。

snippet.txt
{
  "scripts": {
    "lint": "oxlint --type-aware --deny-warnings",
    "format": "oxfmt",
    "format:check": "oxfmt --check"
  }
}

OxfmtのsortImportsを設定し、必要に応じて独立したside_effectグループを設けるなど、既存のグループ分けを維持します。Tailwindの並べ替えでは、sortTailwindcss.stylesheetにデザインシステムのスタイルシートを指定し、cnやcvaなどのクラス構築関数も含めます。固定したバージョンで各設定がサポートされているか確認してください。

規約をコードに落とし込む#

各規約には、目的を満たす最小限の適用手段を使います。インポート順とTailwindクラス順はフォーマットで、インポートの制限はリントルールで扱います。アロー関数ではなく関数宣言を使う場面など、文脈が必要な判断はドキュメントに残します。

リントエラーには、理由と置き換え方法の両方を示します。ロケール対応のナビゲーションラッパーが必須のアプリケーションなら、インポート制限のメッセージは次のようにすると有用です。「@/i18n/navigationのLinkを使ってください。next/linkから直接インポートすると、このアプリケーションのロケール処理が適用されません。」これで、開発者もコーディングエージェントも修正に必要な情報を得られます。

例外は明示し、範囲を絞ります。デフォルトエクスポートを禁止する場合は、ファイルパターンによるオーバーライドで、それを必須とするフレームワークのファイルを除外します。無効にしたルールには、その理由と有効化する条件をコメントで記します。規約を不向きなルールに無理に当てはめてはいけません。REALITYは、意図した範囲を超えて174件の違反が発生したため、関数の記述形式を制限するルールの採用を見送りました。

4つのコミットで移行する#

移行内容を確認しやすく保ちます。

1. 既存ツールを残したまま、Oxlint、Oxfmtとその設定を追加する。 2. 専用のコミットでリポジトリ全体をフォーマットする。 3. 別のコミットでリント修正を適用し、ルールごとの変更をレビューする。 4. スクリプトとCIを切り替え、不要になった依存関係とタスクを削除する。

REALITYのリント修正段階では、224ファイルがimport typeを使うように変更されました。フォーマットと分けることで、変更の目的を追いやすくなりました。細部も確認してください。インポートの並べ替えでは、当初、副作用インポートの後の空行が削除され、グループ分けの調整が必要になりました。

移行後の構成は、比較可能な条件で計測します。REALITYは、元の構成ではTurborepoのキャッシュを無効にし、1回のウォームアップ後に5回実行した中央値を使いました。合計時間はESLint + Prettierが9.29秒、Biomeが2.69秒、Oxlint + Oxfmtが2.95秒でした。各コマンドにはpnpmの起動時間が約1.1秒含まれ、ルールの網羅性も異なるため、この数値はエンジン単体のベンチマークではなく、ワークフロー全体を表しています。

修正内容とルールの網羅性を確認する#

自動修正によって意味が変わることがあります。REALITYは、型インポートと重複インポートの修正が干渉し、必要な値のインポートが削除されたと報告しています。別の修正では、toHaveBeenCalled()がtoHaveBeenCalledWith()に変わり、「呼び出された」が「引数なしで呼び出された」に置き換わりました。型チェックでは、このアサーションの変化を検出できません。修正をレビューし、型チェックとテストを実行してください。

ルールへの対応は個別に確認します。この移行では、同等のルールがなかったため、eslint-plugin-turboの環境変数ルールを廃止しました。また、カテゴリ単位での有効化では、検証した設定でrules-of-hooksが無効のままでした。ツールのバージョンを固定し、アップグレード時にはフォーマット差分をレビューしてください。Prettier互換であっても、あらゆる場面で同一の出力になるとは限りません。

頻繁に実行するエージェントのフックにも注意が必要です。未使用インポートを削除する修正は、後の編集で使用箇所を追加する前に、そのインポートを消してしまうことがあります。関連するインポートと使用箇所を一度の編集で記述するか、変更が完了してから修正を実行してください。

次のステップ#

移行用ブランチを作成して候補のツールをリポジトリに実行し、フォーマット差分と未対応のルールをレビューしてからCIを変更してください。

出典: https://zenn.dev/reality_tech/articles/oxc-monorepo-20261006

目次