BiomeとESLint・Prettierの違い|新規なら結局どっちを選ぶか

プログラミング

※この記事にはプロモーションが含まれます

Python では uv を使ったことがあって、「Rust で書き直したツールってこんなに速いのか」と驚きました。それ以来、JavaScript 界隈で同じ流れにある Biome がずっと気になっていました。JS は「ちょっと書く」くらいなので、ESLint と Prettier の設定もいつもなんとなくコピペで済ませています。この機会に、3つの関係を自分用に整理してみました。

ひとつ先に書いておくと、Biome についてネットで調べると、記事の時期によって書いてあることがかなり違います。なので、なるべく公式ドキュメントの記述をベースにしています。

この記事でわかること

  • ESLint・Prettier・Biome のそれぞれの役割
  • Biome と「ESLint + Prettier」構成の違い(速度・ルール・型チェック・対応言語)
  • 導入コマンドと設定ファイルの比べ方
  • ESLint から Biome に移るときのルール名の違いと注意点
  • 初心者目線でどっちを選ぶか(あくまで個人的な整理)

そもそも3つのツールは何をしているのか

最初にここがごちゃっとしていたので、整理しておきます。

  • ESLint:リンター。「未使用の変数がある」「== を使っている」みたいな、バグの元になりそうな書き方を見つけてくれる
  • Prettier:フォーマッター。インデント・クォート・改行位置など、見た目をそろえる
  • Biome:リンターとフォーマッターの両方を1つでこなすツール。Rust 製で、もとは Rome というプロジェクトからフォークして生まれた

つまり比較するなら「Biome 対 ESLint」ではなく、「Biome 1つ」対「ESLint + Prettier の2つ」と考えるのが正確っぽいです。

ESLint + Prettier 構成でよく聞くのが、「両方が整形のルールを持っていてケンカする」問題です。なので eslint-config-prettier を入れて ESLint 側の整形ルールを切る、というのがお決まりの手順になっています。Biome の公式ドキュメントでも、リンターとフォーマッターで役割を分ける設計だと説明されているようです。最初から役割を分けてあるので、そもそもケンカが起きにくいわけですね。

Biome と ESLint + Prettier の違いを比べてみた

速度

Biome を選ぶ一番の理由としてよく挙がるのがここです。複数のベンチマークで、ESLint と Prettier を別々に動かすより大幅に速いというデータが報告されています。「1万ファイルの lint が ESLint で45秒、Biome で0.8秒」のような数字が出ていたりします。ただ、どちらも測った人や環境によって変わる数字なので、「桁が違うくらい速いらしい」くらいに受け取っておくのがよさそうです。

Biome はファイルを1回パースするだけで、lint と format を同じ流れで処理するのが速さの理由のひとつと言われています。ESLint と Prettier はそれぞれ別にパースするので、そこで差がつくのは納得感があります。

ルール数とプラグイン

ここが「記事によって言ってることが違う」の代表例でした。

  • 2025年ごろの比較記事:「Biome は約200ルール」
  • 2026年1月時点の記事:「v2.3 で423ルール以上」
  • 執筆時点の公式サイト:「ESLint・TypeScript ESLint などを由来とする670ルール」

短い間に3倍以上に増えていて、更新がかなり速いです。公式の比較ページには、eslint-plugin-react、jsx-a11y、import、unicorn あたりの人気プラグインからも多くのルールを移植した、と書かれています。

とはいえ ESLint には10年分のエコシステムがあって、プラグインを入れればルールは数千単位になります。社内独自のルールや、ニッチなフレームワーク向けのプラグインがある場合は、まだ ESLint が強いと思います。Biome も v2 で GritQL ベースのプラグインに対応しました。公式サイトのトップを見ると、v2.6 では JavaScript プラグインも入ったようです。

型情報を使った lint

個人的に一番おもしろかったのがここです。

ESLint で「await し忘れた Promise を検出する」(no-floating-promises) のような型情報が必要なルールを使うには、typescript-eslint と TypeScript コンパイラが必要です。プロジェクト全体の型を解析するので、遅くなりやすいと言われています。

Biome は v2(コードネーム Biotype)で、TypeScript コンパイラに頼らず、自前の型推論で型を使った lint をする仕組みを入れました。型を使うルールの検出精度は、時系列で改善されているようです。TypeScript 本体をインストールしなくていい、というのはなかなか攻めた設計だなと思います。

ただ公式も、型を使うルールの数は typescript-eslint よりかなり少ないと認めています。「型チェック系を厳しく効かせたい」なら、今のところは ESLint 側に分がありそうです。

それから、ネットの記事には「Biome は型を使うルールに対応していない」「react-hooks のルールが無い」と書かれているものもまだあります。でも公式のルール一覧を見ると、useHookAtTopLevel(rules-of-hooks 相当)や useExhaustiveDependencies(exhaustive-deps 相当)がちゃんとありました。古い情報が混ざっているので注意です。

対応言語

公式サイトによると、Biome はいろいろな言語に対応していますが、対応状況は言語ごとに「フルサポート」「一部サポート」「experimental」みたいに段階があるようです。v2.3 では Vue・Svelte・Astro ファイルへの対応も入りました(experimental 扱い)。Prettier も対応言語が多いので、ここは大差ないかもしれません。ただ、Vue や Svelte で細かいルールまで効かせたいなら、ESLint のフレームワーク別プラグインのほうが成熟していると言われています。

導入手順をコマンドで比べる

ESLint + Prettier の場合、だいたいこんな流れになります。

npm init @eslint/config@latest
npm i -D -E prettier eslint-config-prettier
npx eslint .
npx prettier . --write

ESLint は v9 から flat config(eslint.config.js)が標準になりました。そのため、ネットで見つかる .eslintrc 前提の記事をそのまま真似すると動かない、という話をよく見かけます。初学者がつまずきやすいのはここかなと思います。

Biome はこれだけです。

npm i -D -E @biomejs/biome
npx @biomejs/biome init
npx @biomejs/biome check --write .

check を使うと、lint・format・import の並べ替えを一度にやってくれます。init で生成される biome.json に少し手を加えると、こんな感じになります。

{
  "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
  "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
  "linter": {
    "enabled": true,
    "rules": { "recommended": true }
  },
  "assist": {
    "actions": { "source": { "organizeImports": "on" } }
  },
  "javascript": {
    "formatter": { "quoteStyle": "single" }
  }
}

v1 系の記事だと organizeImports がトップレベルに書かれていますが、v2 からは assist の下に移っています。古い設定を貼ると怒られるポイントなので注意です。init で生成すると $schema も入るので、エディタ補完が効いてかなり楽になります。

設定ファイルが1つで済むのは、本当に大きいと思います。ESLint + Prettier だと eslint.config.js・.prettierrc・.prettierignore……と増えていくので。

ESLint から移行するときのルール名の違い

既存プロジェクトを移すためのコマンドも用意されています。

npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write

既存の ESLint / Prettier の設定を読んで biome.json に変換してくれるそうです。サイボウズのフロントエンドチームの記事でも、ESLint でよく使われる recommended ルールの8割以上は Biome にも実装されている、と整理されていました。

ややこしいのはルール名です。ESLint はケバブケース(no-unused-vars)ですが、Biome はキャメルケースで、しかも名前自体が違うことがあります。公式でも例として、ESLint の eqeqeq が Biome では noDoubleEquals になると紹介されていました。単純にキャメルケースへ変換するだけでは対応しないわけです。

頭の整理用に、よく使うルールの対応を Python でメモしてみました。JS のツールの話なのに Python で書いているのは、まあ慣れの問題です。

RULE_MAP = {
    "eqeqeq": "suspicious/noDoubleEquals",
    "no-unused-vars": "correctness/noUnusedVariables",
    "no-debugger": "suspicious/noDebugger",
    "prefer-const": "style/useConst",
    "no-console": "suspicious/noConsole",
    "@typescript-eslint/no-explicit-any": "suspicious/noExplicitAny",
    "react-hooks/rules-of-hooks": "correctness/useHookAtTopLevel",
    "react-hooks/exhaustive-deps": "correctness/useExhaustiveDependencies",
}


def to_camel(name: str) -> str:
    base = name.split("/")[-1]
    head, *rest = base.split("-")
    return head + "".join(w.capitalize() for w in rest)


my_eslint_rules = [
    "eqeqeq",
    "no-console",
    "prefer-const",
    "react-hooks/exhaustive-deps",
    "my-company/no-legacy-api",
]

for rule in my_eslint_rules:
    biome = RULE_MAP.get(rule)
    if biome:
        print(f"{rule:32} -> {biome}")
    else:
        # ここ注意: 単純変換で一致するとは限らない(eqeqeq がいい例)
        print(f"{rule:32} -> ??? (camelCase案: {to_camel(rule)})")

実際に実行した結果
▲実際にこのブログの裏側で実行してみた結果です

Biome のルールは suspicious・correctness・style のようなグループに分かれていて、biome.json でもこのグループ単位で書きます。ここも ESLint との違いですね。最後の my-company/... みたいな社内独自ルールは、当然 Biome 側には存在しません。

そういうルールがある場合の現実的な落とし所として、Biome と ESLint の併用がよく紹介されています。整形と大半の lint は Biome に任せて、Biome にないルールだけ小さな ESLint 設定で動かす、という形です。最初は「2つ入れたら意味なくない?」と思いました。でも ESLint 側が軽くなるだけでも十分速くなるらしいので、移行期のやり方としてはアリかもしれません。

あと公式ドキュメントには、移行直後に新しく出てくる違反を一括で抑制コメントにしておいて、あとから少しずつ直していくやり方も載っていました。いきなり全部直さなくていいのは、心理的にだいぶ助かります。

結局どっちを選ぶか(個人的な整理)

調べた範囲での、自分なりの整理です。

  • 新規の個人プロジェクト・小〜中規模:Biome でいい気がする。設定1ファイル、コマンド1つ、速い
  • 型を使った lint を厳しく効かせたい TypeScript プロジェクト:今はまだ ESLint + typescript-eslint が安心。ただ Biome の追い上げは速い
  • 独自ルールや特定フレームワークのプラグインに依存している既存プロジェクト:ESLint 継続か、Biome との併用
  • とりあえず整形だけそろえたい:Prettier 単体か Biome のフォーマッターだけ。Biome のフォーマッターは Prettier 互換を目指していて、高い互換性があるという話もある

ちなみに公式の比較ページには、Oxc(Oxlint)というもう1つの Rust 製の選択肢も載っていました。ESLint と同じルール名・オプションを使っていて、ESLint のプラグインもそのまま動くものが多いらしいです。「ESLint の資産を活かしつつ速くしたい」ならこっちも候補になりそうです。

余談ですが、AWS の日次コストを集計して Web ページに出す仕組みを Lambda で作っていて、その表示部分をもう3か月くらい放置しています。あれのフロントの JS を触るときに、まず Biome を入れてみようかなと思っています。

まとめ

Biome は「ESLint + Prettier の2つを、1つの速いツールにまとめたもの」で、v2 以降は自前の型推論やプラグインにも対応して、かなり実用的になってきているようです。一方で、ルールの厚みや型チェックの網羅性はまだ ESLint 側に分があります。自分みたいに JS をちょっと書く程度の人なら、新しく始めるときは Biome、既存のものは無理に移さない、くらいがちょうどいいのかなと思いました。

気になっているのは、Biome の型推論がどこまで typescript-eslint に追いつくかです。Python の Ruff や uv みたいに「気づいたらみんなこっちを使っている」状態になるのか、来年あたりまた調べ直してみたいです。

タイトルとURLをコピーしました