Biome 2.0登場 - ESLint/Prettierを置き換える超高速ツールチェーン

2025.06.25

公式ドキュメント

Biomeは、Rust製の超高速なJavaScript/TypeScriptツールチェーンです。ESLintとPrettierの機能を1つのツールに統合し、圧倒的な速度で開発体験を向上させます。2025年、Biome 2.0のリリースにより、さらに多くのプロジェクトでの採用が進んでいます

Biomeとは

ツールチェーンの比較

flowchart TB
 subgraph Traditional["従来の構成"]
 Workflow1["開発ワークフロー"]
 ESLint["ESLint<br/>(JavaScript)"]
 Prettier["Prettier<br/>(JavaScript)"]
 TSC["TypeScript<br/>tsc"]
 Config1["設定ファイルが複数必要<br/>(.eslintrc, .prettierrc, tsconfig.json)"]

 Workflow1 --> ESLint
 Workflow1 --> Prettier
 Workflow1 --> TSC
 ESLint --> Config1
 Prettier --> Config1
 TSC --> Config1
 end
flowchart TB
 subgraph BiomeArch["Biomeの構成"]
 Workflow2["開発ワークフロー"]
 Biome["Biome (Rust)<br/>✓ Linter<br/>✓ Formatter<br/>✓ Import Sort"]
 Config2["biome.json 1ファイルで管理"]

 Workflow2 --> Biome --> Config2
 end

パフォーマンス比較

ツール1000ファイル処理メモリ使用量
ESLint + Prettier約30秒~500MB
Biome約0.5秒~50MB

約60倍高速、メモリ1/10

インストールとセットアップ

基本インストール

# 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

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

# 設定ファイルの初期化
npx @biomejs/biome init

基本的な設定ファイル

// biome.json
{
 "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
 "organizeImports": {
 "enabled": true
 },
 "linter": {
 "enabled": true,
 "rules": {
 "recommended": true
 }
 },
 "formatter": {
 "enabled": true,
 "indentStyle": "space",
 "indentWidth": 2,
 "lineWidth": 100
 },
 "javascript": {
 "formatter": {
 "quoteStyle": "single",
 "trailingCommas": "all",
 "semicolons": "always"
 }
 }
}

package.jsonのスクリプト設定

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

詳細な設定

完全な設定例

{
 "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
 "files": {
 "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx"],
 "ignore": [
 "node_modules",
 "dist",
 "build",
 ".next",
 "coverage",
 "*.min.js"
 ]
 },
 "vcs": {
 "enabled": true,
 "clientKind": "git",
 "useIgnoreFile": true
 },
 "organizeImports": {
 "enabled": true
 },
 "linter": {
 "enabled": true,
 "rules": {
 "recommended": true,
 "complexity": {
 "noExcessiveCognitiveComplexity": {
 "level": "warn",
 "options": {
 "maxAllowedComplexity": 15
 }
 },
 "noForEach": "warn"
 },
 "correctness": {
 "noUnusedVariables": "error",
 "noUnusedImports": "error",
 "useExhaustiveDependencies": "warn"
 },
 "performance": {
 "noAccumulatingSpread": "warn",
 "noDelete": "warn"
 },
 "security": {
 "noDangerouslySetInnerHtml": "error"
 },
 "style": {
 "noNonNullAssertion": "warn",
 "useConst": "error",
 "useTemplate": "error",
 "noParameterAssign": "error"
 },
 "suspicious": {
 "noExplicitAny": "warn",
 "noConsoleLog": "warn",
 "noDebugger": "error"
 },
 "nursery": {
 "useSortedClasses": {
 "level": "warn",
 "options": {
 "attributes": ["className", "class"],
 "functions": ["clsx", "cn", "cva"]
 }
 }
 }
 }
 },
 "formatter": {
 "enabled": true,
 "formatWithErrors": false,
 "indentStyle": "space",
 "indentWidth": 2,
 "lineEnding": "lf",
 "lineWidth": 100,
 "attributePosition": "auto"
 },
 "javascript": {
 "formatter": {
 "enabled": true,
 "quoteStyle": "single",
 "jsxQuoteStyle": "double",
 "quoteProperties": "asNeeded",
 "trailingCommas": "all",
 "semicolons": "always",
 "arrowParentheses": "always",
 "bracketSpacing": true,
 "bracketSameLine": false
 },
 "parser": {
 "unsafeParameterDecoratorsEnabled": true
 }
 },
 "json": {
 "formatter": {
 "enabled": true,
 "indentStyle": "space",
 "indentWidth": 2,
 "lineWidth": 100
 }
 },
 "css": {
 "formatter": {
 "enabled": true,
 "indentStyle": "space",
 "indentWidth": 2,
 "lineWidth": 100,
 "quoteStyle": "double"
 },
 "linter": {
 "enabled": true
 }
 },
 "overrides": [
 {
 "include": ["*.test.ts", "*.test.tsx", "*.spec.ts"],
 "linter": {
 "rules": {
 "suspicious": {
 "noExplicitAny": "off"
 }
 }
 }
 },
 {
 "include": ["*.config.js", "*.config.ts"],
 "linter": {
 "rules": {
 "style": {
 "noDefaultExport": "off"
 }
 }
 }
 }
 ]
}

Linterルールのカテゴリ

ルールカテゴリ一覧

カテゴリルール例説明
a11y (アクセシビリティ)useAltText画像にalt属性を要求
useKeyWithClickEventsクリックイベントにキー操作
complexity (複雑性)noBannedTypes禁止された型の使用を検出
noForEachforEach → for…of を推奨
noExcessiveCognitiveComplexity認知的複雑度制限
correctness (正確性)noUnusedVariables未使用変数の検出
noUnusedImports未使用インポートの検出
useExhaustiveDependenciesuseEffect依存配列
performance (パフォーマンス)noAccumulatingSpreadスプレッド演算子の累積禁止
noDeletedelete演算子の使用を警告
security (セキュリティ)noDangerouslySetInnerHtmlXSS脆弱性の検出
noGlobalEvaleval()の使用禁止
style (スタイル)useConst再代入されない変数はconstを使用
useTemplate文字列連結よりテンプレートリテラル
noParameterAssignパラメータへの再代入禁止
suspicious (疑わしいコード)noExplicitAnyany型の使用を警告
noConsoleLogconsole.logの使用を警告
noDebuggerdebugger文の禁止

ルールの詳細設定例

{
 "linter": {
 "rules": {
 "correctness": {
 "useExhaustiveDependencies": {
 "level": "warn",
 "options": {
 "hooks": [
 {
 "name": "useQuery",
 "stableResult": [1]
 },
 {
 "name": "useMutation",
 "stableResult": [1]
 },
 {
 "name": "useCustomHook",
 "closureIndex": 0,
 "dependenciesIndex": 1
 }
 ]
 }
 }
 }
 }
 }
}

ESLint/Prettierからの移行

移行チェックリスト

# 1. Biomeのインストール
npm install --save-dev @biomejs/biome

# 2. 設定ファイルの初期化
npx @biomejs/biome init

# 3. ESLint設定からの移行(自動)
npx @biomejs/biome migrate eslint --write

# 4. Prettier設定からの移行(自動)
npx @biomejs/biome migrate prettier --write

ESLintルールの対応表

ESLintBiomeカテゴリ
no-unused-varsnoUnusedVariablescorrectness
no-consolenoConsoleLogsuspicious
eqeqeqnoDoubleEqualssuspicious
prefer-constuseConststyle
no-varnoVarstyle
@typescript-eslint/no-explicit-anynoExplicitAnysuspicious
react-hooks/exhaustive-depsuseExhaustiveDependenciescorrectness
jsx-a11y/alt-textuseAltTexta11y

段階的な移行戦略

// biome.json - 段階的移行用設定
{
 "linter": {
 "enabled": true,
 "rules": {
 "recommended": true,
 // 最初は警告のみ
 "correctness": {
 "noUnusedVariables": "warn",
 "noUnusedImports": "warn"
 },
 "suspicious": {
 "noExplicitAny": "warn",
 "noConsoleLog": "off" // 最初は無効化
 }
 }
 }
}
# 移行後にESLint/Prettierを削除
npm uninstall eslint prettier eslint-config-prettier eslint-plugin-*

# 設定ファイルの削除
rm .eslintrc* .prettierrc* .eslintignore .prettierignore

エディタ統合

VS Code

// .vscode/extensions.json
{
 "recommendations": ["biomejs.biome"]
}
// .vscode/settings.json
{
 // Biomeをデフォルトフォーマッターに
 "editor.defaultFormatter": "biomejs.biome",
 "[javascript]": {
 "editor.defaultFormatter": "biomejs.biome"
 },
 "[typescript]": {
 "editor.defaultFormatter": "biomejs.biome"
 },
 "[typescriptreact]": {
 "editor.defaultFormatter": "biomejs.biome"
 },
 "[json]": {
 "editor.defaultFormatter": "biomejs.biome"
 },

 // 保存時に自動フォーマット
 "editor.formatOnSave": true,

 // 保存時にコードアクション実行
 "editor.codeActionsOnSave": {
 "quickfix.biome": "explicit",
 "source.organizeImports.biome": "explicit"
 },

 // ESLint/Prettierを無効化
 "eslint.enable": false,
 "prettier.enable": false
}

Neovim (nvim-lspconfig)

-- init.lua
require('lspconfig').biome.setup({
 cmd = { 'npx', 'biome', 'lsp-proxy' },
 root_dir = require('lspconfig.util').root_pattern('biome.json', 'biome.jsonc'),
 single_file_support = false,
})

-- null-ls.nvimとの統合
local null_ls = require('null-ls')
null_ls.setup({
 sources = {
 null_ls.builtins.formatting.biome,
 null_ls.builtins.diagnostics.biome,
 },
})

JetBrains IDE (WebStorm等)

設定手順:

  1. Settings → Languages & Frameworks → JavaScript → Code Quality Tools → Biome
  2. “Enable” にチェック
  3. Biome package: node_modules/@biomejs/biome
  4. Configuration file: biome.json

フォーマット設定:

  1. Settings → Editor → Code Style
  2. “Enable EditorConfig support” をオフ
  3. Settings → Tools → Actions on Save
  4. “Reformat code” と “Run Biome” にチェック

CI/CD統合

GitHub Actions

# .github/workflows/ci.yml
name: CI

on:
 push:
 branches: [main]
 pull_request:
 branches: [main]

jobs:
 lint:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4

 - name: Setup Node.js
 uses: actions/setup-node@v4
 with:
 node-version: '20'
 cache: 'npm'

 - name: Install dependencies
 run: npm ci

 - name: Run Biome CI
 run: npx @biomejs/biome ci .

 # PRにインライン注釈を追加
 lint-review:
 runs-on: ubuntu-latest
 if: github.event_name == 'pull_request'
 permissions:
 contents: read
 pull-requests: write
 steps:
 - uses: actions/checkout@v4

 - name: Setup Biome
 uses: biomejs/setup-biome@v2
 with:
 version: latest

 - name: Run Biome with reviewdog
 uses: reviewdog/action-biome@v1
 with:
 github_token: ${{ secrets.GITHUB_TOKEN }}
 reporter: github-pr-review

GitLab CI

# .gitlab-ci.yml
stages:
 - lint

biome:
 stage: lint
 image: node:20-alpine
 cache:
 key: ${CI_COMMIT_REF_SLUG}
 paths:
 - node_modules/
 script:
 - npm ci
 - npx @biomejs/biome ci .
 rules:
 - if: $CI_PIPELINE_SOURCE == "merge_request_event"
 - if: $CI_COMMIT_BRANCH == "main"

pre-commitフック (Husky + lint-staged)

# Huskyのインストール
npm install --save-dev husky lint-staged
npx husky init
// package.json
{
 "lint-staged": {
 "*.{js,jsx,ts,tsx,json,css}": [
 "biome check --write --no-errors-on-unmatched"
 ]
 }
}
# .husky/pre-commit
npx lint-staged

高度な使用方法

プラグインAPI(実験的機能)

// biome-plugin.js - カスタムルールの例
export default {
 name: 'my-custom-rules',
 rules: {
 noTodoComments: {
 meta: {
 docs: {
 description: 'Disallow TODO comments in production code',
 },
 },
 create(context) {
 return {
 Comment(node) {
 if (node.value.includes('TODO')) {
 context.report({
 node,
 message: 'TODO comments should be resolved before merge',
 });
 }
 },
 };
 },
 },
 },
};

Monorepo設定

// ルートのbiome.json
{
 "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
 "extends": [],
 "files": {
 "ignore": ["packages/*/dist", "packages/*/node_modules"]
 },
 "linter": {
 "enabled": true,
 "rules": {
 "recommended": true
 }
 },
 "formatter": {
 "enabled": true
 }
}
// packages/web/biome.json - パッケージ固有の設定
{
 "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
 "extends": ["../../biome.json"],
 "linter": {
 "rules": {
 "correctness": {
 "useExhaustiveDependencies": "warn"
 }
 }
 }
}

カスタムインポートソート

{
 "javascript": {
 "organizeImports": {
 "groups": [
 ["react", "react-dom"],
 ["^@?\\w"],
 ["^@/"],
 ["^\\.\\."],
 ["^\\."]
 ]
 }
 }
}

トラブルシューティング

よくある問題と解決策

# キャッシュのクリア
rm -rf node_modules/.cache/biome

# 詳細なエラー出力
npx @biomejs/biome check --verbose .

# 特定のファイルのデバッグ
npx @biomejs/biome lint --verbose src/problematic-file.ts

# 設定の検証
npx @biomejs/biome check --config-path biome.json --verbose

エラー抑制コメント

// ファイル全体で特定のルールを無効化
// biome-ignore-all lint/suspicious/noExplicitAny: Legacy code

// 次の行のみ無効化
// biome-ignore lint/suspicious/noExplicitAny: Necessary for this API
const data: any = response.data;

// 複数ルールの無効化
// biome-ignore lint/style/useConst lint/correctness/noUnusedVariables: Intentional
let unusedVar = 'test';

// フォーマットの無効化
// biome-ignore format: Keep this formatting
const matrix = [
 [1, 0, 0],
 [0, 1, 0],
 [0, 0, 1],
];

パフォーマンスベンチマーク

大規模プロジェクトでの比較(10,000ファイル):

ツールlint時間format時間メモリ使用量
ESLint120秒-1.2GB
Prettier-45秒800MB
ESLint+Prettier165秒(合計)2.0GB
Biome2秒1.5秒150MB
改善率60x高速30x高速13x削減

まとめ

Biomeは、フロントエンド開発のツールチェーンを大きく改善します。

Biome導入のメリット

項目ESLint+PrettierBiome
速度遅い超高速(60倍以上)
設定ファイル複数1ファイル
依存関係多数1つ
メモリ使用量
設定の一貫性衝突の可能性統合済み

導入推奨ケース

  • 新規プロジェクト
  • CIの高速化が必要なプロジェクト
  • 設定の簡素化を求めるチーム
  • Monorepo環境

Biomeは、JavaScriptエコシステムの新しいスタンダードとなりつつあります。

参考リソース

← 一覧に戻る
PR
PR
PR
PR