ESLintからBiomeに移行しました

こんにちは。フロントエンドエンジニアのiemongです。
noteで開発しているmonorepo環境のLinterをESLintからBiomeへほぼ移行しました。それについて共有します。

移行のモチベーション

noteではNuxtからNext.jsへのリプレイスを進めている最中で、monorepo環境で6個のアプリと22個のpackageがあります。TurborepoのRemote Cachingを使うなどしてタスクの実行速度の改善は既にやってたのですが、Componentの数が増えてきたせいかCIでlintが途中でkillしてしまうことがあったり、キャッシュがない場合にLintだけで2~3分かかるpackageなども存在しました。また、ESLintのFlat Config対応も進めていきたかったのですが、使用しているESLintのplugin側の対応がまちまちで着手しづらい状況でした。
それに加えて、Biome v1.7から biome migrate eslint と biome migrate prettierコマンドが追加されたのも試してみるモチベーションになりました。

Biomeの導入

install

pnpm add --save-dev --save-exact @biomejs/biome

init

pnpm biome init

initを実行するとbiome.jsonが生成されます。

ESLintのmigrate

biome migrate eslint --write --include-inspired

実行後、biome.jsonに.eslintrcをベースにしたルールが上書きされます。

Lintの実行

pnpm biome lint --write <files>

手元の環境で実行してみたところ、文字通り秒で終わるようになりました。速い。Biomeに変更したことでエラーが出てる箇所もあったので修正してきます。あと、ついでにPrettierもBiomeへ変更しました。

monorepoでの対応

こちらのドキュメントを参考にroot directoryに基準となるbiome.jsonを用意し、各appやpackageで個別のruleを設定したい場合は、それぞれbiome.jsonを配置するようにしました。

ただし、このやり方だとVS CodeでBiomeのExtensionがMultiple workspaceをまだサポートしてないため、各package,appのbiome.jsonで上書きしたruleはeditor上ではエラーになっている状況でした。なので、極力root directoryのbiome.jsonのruleで完結できるように既存のコードの修正等を加えていきました。

また、移行の間、他の開発に支障がなるべく出ないように、移行前のapp,packageは明示的にignoreして作業を進めました。

{
  "$schema": "https://biomejs.dev/schemas/1.8.2/schema.json",
  "organizeImports": { "enabled": true },
  "linter": {
    "enabled": true,
    "ignore": ["apps/hoge-app/**", "packages/fuga-package/**", "**/dist/**", "**/node_modules/**"],
    "rules": {
      "recommend": true
    }
  }
}

また、Next.jsのアプリケーションではeslint-config-turboとnext/core-web-vitalsを引き続き使いたかったので、lint実行時にESLintとBiomeの両方を実行するようにしています。

結果

localで↓のコマンドを実行して時間を計測してみました。
lint taskのdependsOnを実行しないためにonlyオプションをつけています

hyperfine --warmup 3 'pnpm lint --force --no-cache --only'

実行結果
Before: 73.172 s ± 2.556 s
After: 5.844 s ± 1.251 s

10倍以上速くなっていますね✨



▼noteの技術記事が読みたい方はこちら

そういえば、推しのアイドルグループのEPの発売したので、とりあえず聞いてみてほしい