ESLint + PrettierからBiomeへ移行する完全ガイド【2026年版】

開発

ESLint + Prettier の設定ファイル、気づいたら 100 行超えていませんか?Biome へ移行すれば、設定が 75 行→22 行に削減され、lint の実行速度が約 15 倍速くなります。この記事では、移行手順から「import order は対応してる?」「React hooks rules は?」「v2.0 の CPU 問題は?」といった実務で気になるポイントまで、すべて解説します。

ESLintの複雑な設定ファイルとBiomeのシンプルな設定ファイルの比較、左は60行以上のeslintrc.js、右は7行のbiome.json

Biomeとは?ESLintとPrettierを置き換えるRust製ツール

Biome は、ESLint(リンター)と Prettier(フォーマッター)の機能を 1 つにまとめた Rust 製のツールです。2023 年に Rome からフォークされ、現在も活発に開発が続いています。

主な特徴

  • Prettier より約 25 倍高速なフォーマット
  • ESLint より約 15 倍高速な lint
  • 設定ファイルが 1 つ(biome.json)にまとまる
  • JavaScript、TypeScript、JSON、CSS に対応

海外の開発者の間では「ESLint 設定地獄からの解放」として注目を集めていて、日本でも採用事例が増えてきました。

移行前に確認:Biomeで対応していないルール

移行する前に、今使っている ESLint プラグインが Biome で対応しているか確認しておきましょう。

flowchart LR
    subgraph ESLint["ESLint Plugins"]
        A[react-hooks]
        B[import]
        C[cypress]
        D[jest]
    end

    subgraph Biome["Biome Rules"]
        E[useHookAtTopLevel]
        F[useExhaustiveDependencies]
        G[organizeImports]
        H[noCommonJs]
    end

    A -->|対応| E
    A -->|対応| F
    B -->|一部| G
    B -->|対応| H
    C -->|非対応| X[ESLint併用]
    D -->|一部| X

eslint-plugin-react-hooks → 対応済み

React hooks 関連のルールは、Biome でほぼ同等の機能が提供されています。

ESLintBiome対応状況
rules-of-hooksuseHookAtTopLevel同等
exhaustive-depsuseExhaustiveDependencies同等

useExhaustiveDependenciesは、useEffectuseMemouseCallbackなどの依存配列をチェックしてくれます。カスタム hooks も設定で追加できます。

{
  "linter": {
    "rules": {
      "correctness": {
        "useExhaustiveDependencies": {
          "level": "error",
          "options": {
            "hooks": [
              {
                "name": "useCustomEffect",
                "closureIndex": 0,
                "dependenciesIndex": 1
              }
            ]
          }
        }
      }
    }
  }
}

eslint-plugin-import → 一部対応

import 関連のルールは一部対応しています。

ESLintBiome対応状況
no-commonjsnoCommonJs対応
no-default-exportnoDefaultExport対応
no-extraneous-dependenciesnoUndeclaredDependencies対応
orderorganizeImports別機能として提供

import orderの設定方法

「import 順のソートはできるの?」という質問をよく見かけます。Biome にはorganizeImportsというアシスト機能があり、eslint-plugin-import/order@trivago/prettier-plugin-sort-importsと同様のことができます。

デフォルトのソート順は「モジュールからの距離」で決まります。

  1. URLs(https://example.org
  2. プロトコル付きパッケージ(node:pathbun:test
  3. 外部パッケージ(react@my/lib
  4. エイリアス(@/#~
  5. 相対パス(./../

カスタマイズしたい場合はgroupsオプションを使います。

{
  "assist": {
    "actions": {
      "source": {
        "organizeImports": {
          "level": "on",
          "options": {
            "groups": [
              [":BUN:", ":NODE:"],
              ":BLANK_LINE:",
              ":PACKAGE:",
              ":BLANK_LINE:",
              "@/**",
              ":BLANK_LINE:",
              ":PATH:"
            ]
          }
        }
      }
    }
  }
}

これで、Node.js 組み込みモジュール → 外部パッケージ → プロジェクト内エイリアス → 相対パス、という順番でソートされ、間に空行が入ります。

対応していない主なプラグイン

以下のプラグインには、現時点で Biome 側に同等機能がありません。

  • eslint-plugin-cypress: Cypress 特有のルール
  • eslint-plugin-jest: Jest 特有のルール(一部のみ対応)
  • eslint-plugin-graphql: GraphQL の lint

これらを使っている場合は、Biome と ESLint を併用するか、移行を見送る判断も必要です。

実際の移行手順(3ステップ)

それでは実際の移行手順を見ていきましょう。公式のbiome migrateコマンドを使えば、既存の設定を自動で変換できます。

flowchart TD
    A[Step 1: Biomeインストール] --> B[Step 2: 設定移行]
    B --> C[Step 3: 設定最適化]

    A --> A1["npm install @biomejs/biome"]
    B --> B1["biome init"]
    B1 --> B2["biome migrate eslint --write"]
    B2 --> B3["biome migrate prettier --write"]
    C --> C1["recommended: true で簡潔化"]
    C1 --> D[移行完了]

Step 1: Biomeのインストール

# npm
npm install --save-dev --save-exact @biomejs/biome

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

# yarn
yarn add --dev --exact @biomejs/biome

--save-exactを付けているのは、Biome はセマンティックバージョニングに準拠していないため、マイナーバージョンでも破壊的変更が入る可能性があるからです。

Step 2: 既存設定の移行

初期設定ファイルを生成してから、ESLint と Prettier の設定を移行します。

# 初期設定ファイルの生成
npx biome init

# ESLint設定の移行
npx biome migrate eslint --write

# Prettier設定の移行
npx biome migrate prettier --write

biome migrate eslintは、.eslintrc.jseslint.config.js(Flat Config)を読み取り、対応する Biome ルールに変換します。変換できないルールは、コメントとしてbiome.jsonに記録されるので、後から確認できます。

Step 3: 設定の最適化

移行直後のbiome.jsonは冗長になりがちです。Biome の推奨ルール(recommended: true)を有効にすると、多くのルールを明示的に書かなくて済みます。

{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "javascript": {
    "formatter": {
      "semicolons": "asNeeded",
      "quoteStyle": "single"
    }
  }
}

ある海外の事例では、この最適化によってESLint設定が75行→22行に、Prettier設定が40行→29行に削減されたそうです。

package.jsonのスクリプト更新

移行後はpackage.jsonのスクリプトを更新しましょう。

{
  "scripts": {
    "lint": "biome lint .",
    "format": "biome format --write .",
    "check": "biome check --write ."
  }
}

biome checkは lint と format を同時に実行します。--writeオプションで自動修正も行います。

lint-stagedとの連携

pre-commit フックで Biome を使う場合:

{
  "lint-staged": {
    "*": ["biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"]
  }
}

--files-ignore-unknown=trueを付けることで、Biome が対応していないファイル(画像など)でエラーになるのを防げます。

Biome v2.0のCPU暴走問題と対策

「Biome v2.0 にしたら CPU 使用率が 100%になる」という報告が、2025 年 6 月ごろから増えました。実際に GitHub には複数の issue が上がっています。

flowchart LR
    subgraph Problem["問題 v2.0-v2.1.2"]
        P1["useHookAtTopLevel<br/>無限再帰バグ"]
        P2["ブランチ切替時<br/>CPU高負荷"]
    end

    subgraph Fix["修正"]
        F1["PR #6931<br/>2025年7月"]
    end

    subgraph Status["現在"]
        S1["v2.1.3以降<br/>解消済み"]
    end

    P1 --> F1 --> S1
    P2 -.->|一部継続| W["回避策:<br/>ルールOFF"]

問題の原因

主な原因は 2 つ特定されています。

  1. useHookAtTopLevelルールの無限再帰バグ:自分自身を呼び出す hook 関数があると、linter がハングする
  2. ブランチ切り替え時の CPU 高負荷:WebStorm/IntelliJ 環境で、git branch 切り替え時に biome プロセスが数秒間 100% CPU を使う

修正状況

useHookAtTopLevelのバグは、2025年7月のPR #6931で修正済みです。v2.1.3 以降では解消されているはずです。

もしまだ問題が発生する場合は、以下の対策を試してください。

{
  "linter": {
    "rules": {
      "correctness": {
        "useHookAtTopLevel": "off"
      }
    }
  }
}

一時的にルールをオフにして、次のリリースを待つのも手です。

パフォーマンス調査方法

Biome が遅いと感じたら、公式のパフォーマンス調査ガイドが参考になります。BIOME_LOG_LEVEL=debug環境変数を設定すると、詳細なログが出力されます。

ESLintとの併用は可能?

「一部のルールは ESLint のまま使いたい」という場合、Biome と ESLint の併用も可能です。

例えば、フォーマットは Biome、Cypress 特有のルールは ESLint、という使い分けができます。

// biome.json
{
  "formatter": { "enabled": true },
  "linter": { "enabled": true }
}
// eslint.config.js
import cypress from 'eslint-plugin-cypress';

export default [
  {
    plugins: { cypress },
    rules: {
      'cypress/no-unnecessary-waiting': 'error'
    }
  }
];

ただし、フォーマットルールが競合しないよう注意が必要です。ESLint 側でフォーマット関連のルール(indentsemiなど)は無効にしておきましょう。

移行後のトラブルシューティング

importが勝手に消える

Biome は未使用の import を自動で削除します。型のみの import が消えてしまう場合は、import typeを明示的に使うか、以下の設定で制御できます。

{
  "linter": {
    "rules": {
      "correctness": {
        "noUnusedImports": "off"
      }
    }
  }
}

VSCodeでBiomeが動かない

  1. Biome 拡張機能がインストールされているか確認
  2. .vscode/settings.jsonに以下を追加:
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "quickfix.biome": "explicit",
    "source.organizeImports.biome": "explicit"
  }
}

GraphQLがフォーマットされない

Biome は GraphQL に対応していません。GraphQL ファイルだけ Prettier を使い続けるか、dprintなどの別ツールを検討してください。

まとめ

ESLint + Prettier から Biome への移行は、biome migrateコマンドのおかげで思ったより簡単です。

移行のメリット

  • 設定ファイルが 1 つになり、行数が大幅削減
  • lint が約 15 倍、フォーマットが約 25 倍高速化
  • 設定の学習コストが低い

注意点

  • eslint-plugin-cypress など、一部プラグインは非対応
  • v2.x には CPU 問題があったが、v2.1.3 以降で修正済み
  • GraphQL は非対応

個人的には、新規プロジェクトなら迷わず Biome、既存プロジェクトは使っている ESLint プラグインとの互換性を確認してから移行を判断するのがおすすめです。

Thanks for reading!
BiomeESLintPrettierJavaScriptTypeScript