eslint vs biome 徹底比較

eslint の詳細biome の詳細
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

ESLint vs Biome(@biomejs/biome) — JavaScript/TypeScript リンター比較

注記: npm上には biome という名前で環境変数管理ツールが存在しますが、本記事では現在JavaScriptエコシステムで広く比較対象となっている @biomejs/biome(旧Rome — 高速なリンター・フォーマッター)と ESLint を比較します。biome(環境変数管理)はESLintと用途がまったく異なるため、比較記事としての実用的価値を優先し、このように構成しました。


1. 結論

既存の大規模プロジェクトや、細かいルールカスタマイズ・豊富なプラグインが必要な場合は ESLint を選んでください。新規プロジェクトで高速なリント+フォーマットを一括導入し、設定の手間を最小限にしたい場合は Biome が最適です。両者は共存も可能なので、段階的な移行という選択肢もあります。


2. 比較表

観点ESLintBiome (@biomejs/biome)
初回リリース2013年2023年(Rome から fork)
実装言語JavaScript (Node.js)Rust
主な機能リンターリンター + フォーマッター + インポート整理
対応言語JS / TS / JSX / TSX(プラグインで Vue, Svelte 等)JS / TS / JSX / TSX / JSON / CSS / GraphQL
ルール数(組み込み)約 300+約 300+(v1.x 時点)
プラグインエコシステム★★★★★(数千のプラグイン)★★☆☆☆(プラグインシステムは開発中)
設定ファイルeslint.config.js(Flat Config)biome.json / biome.jsonc
TypeScript 対応typescript-eslint が必要ゼロ設定で対応
フォーマッター別途 Prettier 等が必要内蔵(Prettier 互換 97%+)
実行速度普通〜遅い非常に高速(10〜100倍)
npm install サイズ~30MB+(プラグイン込み)~10MB 程度
学習コスト中〜高(設定が複雑になりがち)低(少ない設定で始められる)
IDE 対応VS Code, JetBrains 等 充実VS Code 拡張あり、JetBrains 対応中
CI 統合非常に成熟GitHub Actions 等対応済み
ライセンスMITMIT

3. それぞれの強み

ESLint の強み

  • 圧倒的なプラグインエコシステム: eslint-plugin-react, eslint-plugin-import, eslint-plugin-vue, eslint-plugin-testing-library など、あらゆるフレームワーク・ライブラリに対応するプラグインが存在します。
  • カスタムルールの作成が容易: AST ベースの Visitor パターンで独自ルールを JavaScript で記述できます。社内固有のコーディング規約を強制したい場合に強力です。
  • Flat Config による設定の近代化: v9 以降の Flat Config により、設定の共有・合成が格段にシンプルになりました。
  • 長年の実績と情報量: Stack Overflow、ブログ記事、書籍など、トラブルシューティング情報が豊富です。

Biome の強み

  • 圧倒的な速度: Rust 実装により、数千ファイルのプロジェクトでも数百ミリ秒でリント+フォーマットが完了します。
  • オールインワン: リンター・フォーマッター・インポートソートが 1 つのツールに統合されており、eslint + prettier + eslint-plugin-import の組み合わせを置き換えられます。
  • ゼロコンフィグで TypeScript 対応: 追加パッケージなしで TypeScript / JSX / TSX をそのまま解析できます。
  • Prettier 互換のフォーマッター: ESLint と Prettier の競合問題(eslint-config-prettier の設定など)に悩む必要がありません。
  • わかりやすいエラーメッセージ: Rust コンパイラに影響を受けた、詳細で読みやすい診断メッセージを出力します。

4. コード例で比較

セットアップ

# ESLint のセットアップ
npm install -D eslint @eslint/js typescript-eslint

# Biome のセットアップ
npm install -D @biomejs/biome
npx biome init

設定ファイル

ESLint(eslint.config.js)

// eslint.config.js
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  {
    rules: {
      "no-console": "warn",
      "eqeqeq": "error",
      "@typescript-eslint/no-unused-vars": [
        "error",
        { argsIgnorePattern: "^_" },
      ],
    },
  },
  {
    ignores: ["dist/**", "node_modules/**"],
  }
);

Biome(biome.json)

// biome.json
{
  "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "suspicious": {
        "noConsole": "warn"
      },
      "style": {
        "useConst": "error"
      },
      "correctness": {
        "noUnusedVariables": "error"
      }
    }
  },
  "files": {
    "ignore": ["dist/**", "node_modules/**"]
  }
}

同じコードをリントする

以下の TypeScript ファイルを両ツールでチェックしてみます。

// src/example.ts
import { readFileSync } from "fs";
import { join } from "path";
import { tmpdir } from "os";

const getUserData = (id: number) => {
  let name = "Alice";
  var age = 30;
  const unused = "this is never used";

  if (id == 1) {
    console.log("found user");
  }

  return { name, age };
};

export { getUserData };

ESLint の実行と出力

npx eslint src/example.ts
src/example.ts
   1:1   warning  'readFileSync' is defined but never used  @typescript-eslint/no-unused-vars
   3:1   warning  'tmpdir' is defined but never used         @typescript-eslint/no-unused-vars
   8:3   error    Unexpected var, use let or const instead   no-var
   9:9   error    'unused' is assigned but never used        @typescript-eslint/no-unused-vars
  11:7   error    Expected '===' and instead saw '=='        eqeqeq
  12:5   warning  Unexpected console statement               no-console

✖ 6 problems (3 errors, 3 warnings)

Biome の実行と出力

npx biome check src/example.ts
src/example.ts:1:10 lint/correctness/noUnusedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ This import is unused.

  > 1 │ import { readFileSync } from "fs";
      │          ^^^^^^^^^^^^

  ℹ Safe fix: Remove the unused import.

src/example.ts:3:10 lint/correctness/noUnusedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ This import is unused.

  > 3 │ import { tmpdir } from "os";
      │          ^^^^^^

src/example.ts:8:3 lint/style/noVar ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ Use let or const instead of var.

  > 8 │   var age = 30;
      │   ^^^

  ℹ Safe fix: Use 'let' instead.

src/example.ts:9:9 lint/correctness/noUnusedVariables ━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ This variable is unused.

  > 9 │   const unused = "this is never used";
      │         ^^^^^^

src/example.ts:11:7 lint/suspicious/noDoubleEquals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ Use === instead of ==.

  > 11 │   if (id == 1) {
       │       ^^^^^^

  ℹ Safe fix: Use ===.

src/example.ts:12:5 lint/suspicious/noConsole ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ⚠ Don't use console.

  > 12 │     console.log("found user");
       │     ^^^^^^^

Checked 1 file in 5ms. Found 6 diagnostics.

自動修正の比較

# ESLint の自動修正
npx eslint src/example.ts --fix

# Biome の自動修正(リント + フォーマット + インポート整理を一括)
npx biome check src/example.ts --write

Biome は --write 一発で、未使用インポートの削除・varlet への変換・===== への変換・コードフォーマット・インポート整理をすべて実行します。

package.json スクリプトの比較

// ESLint + Prettier 構成
{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check ."
  }
}

// Biome 構成
{
  "scripts": {
    "lint": "biome check .",
    "lint:fix": "biome check . --write",
    "format": "biome format . --write",
    "format:check": "biome format ."
  }
}

5. どちらを選ぶべきか — ユースケース別の推奨

ESLint を選ぶべきケース

ユースケース理由
既存の大規模プロジェクト移行コストが高く、既存の ESLint 設定資産を活かせる
特殊なプラグインが必要eslint-plugin-react-hooks, eslint-plugin-jsx-a11y など Biome 未対応のルールがある
カスタムルールを自作したいJavaScript でルールを書ける柔軟な API がある
Vue / Svelte / Angularフレームワーク固有のプラグインが成熟している
チームが ESLint に慣れている学習コスト・移行コストを避けたい

Biome を選ぶべきケース

ユースケース理由
新規プロジェクトゼロコンフィグで始められ、ツール選定の手間が省ける
React / Next.js の TypeScript プロジェクト追加設定なしで TS + JSX を解析でき、速度も圧倒的
ESLint + Prettier の競合に疲れたリンターとフォーマッターが統合されており、競合が原理的に発生しない
CI の実行時間を短縮したい大規模リポジトリでも数秒で完了する
モノレポ単一バイナリで依存が少なく、インストールが高速
設定をシンプルに保ちたいbiome.json 1 ファイルですべて完結する

段階的な移行(共存)

両者は共存可能です。まず Biome でフォーマッターを導入し、Prettier を置き換えてから、徐々にリントルールも移行するアプローチが現実的です。

# Prettier から Biome フォーマッターへの移行
npx biome migrate prettier --write

# ESLint から Biome リンターへの移行(対応ルールの確認)
npx biome migrate eslint --write

6. まとめ

判断軸推奨
エコシステムの広さ・柔軟性重視ESLint
速度・シンプルさ・オールインワン重視Biome
既存プロジェクトの維持ESLint(当面)
新規プロジェクトの立ち上げBiome(まず試す価値あり)