Biome 全面替代 ESLint + Prettier:性能提升 35 倍的前端工具链实战指南

深入解析 Biome —— 基于 Rust 的下一代 JavaScript/TypeScript 工具链。性能对比实测、从 ESLint + Prettier 迁移完整方案、CI/CD 集成最佳实践,一文搞定。

开发者效率 2026-05-29 12 分钟

🔧 一、Biome 是什么,为什么它能终结 ESLint + Prettier 的统治

2024 年前端工具链领域发生了一件意义深远的事:Biome(原 Rome 的 fork)正式发布 1.0,以 Rust 编写、单一二进制文件的形式,同时提供了代码检查(Linting)和代码格式化(Formatting)能力。到了 2026 年,Biome 的 npm 周下载量已突破 800 万,越来越多的中大型项目开始从 ESLint + Prettier 的组合迁移到 Biome。

为什么这很重要? 一个典型的中型前端项目中,ESLint 的初始化时间约为 3-8 秒,Prettier 格式化全量代码需要 5-12 秒。而 Biome 在同等条件下,lint 耗时约 0.1-0.3 秒,格式化耗时约 0.05-0.2 秒——快了 30-60 倍。这不是微优化,而是开发体验的质变。想象一下,你每次保存文件时不再需要等待 2-3 秒的格式化延迟,保存即格式化的体验变得真正「即时」。

更关键的是架构差异。ESLint 的插件生态虽然庞大,但每个插件都是独立的 JavaScript 模块,解析 AST 时存在大量重复计算——同一个文件可能被解析 5-10 次。Prettier 则需要单独安装、单独配置、与 ESLint 的规则可能冲突(比如缩进策略)。Biome 将解析(Parser)、检查(Linter)、格式化(Formatter)统一到一个 Rust crate 中,共享同一个 CST(Concrete Syntax Tree),从根本上消除了冗余。

此外,Biome 的安装体验也大幅简化。ESLint + Prettier 的完整安装通常需要 8-15 个 npm 依赖(eslint、prettier、各种插件和配置包),而 Biome 只有一个 @biomejs/biome 包,无任何 peer dependency。这意味着更少的供应链攻击面、更稳定的版本锁定、以及更快的 CI 安装速度。

📌 记住: Biome 的目标不是成为 ESLint 的替代品,而是成为整个 JavaScript 工具链的基础设施。它正在逐步添加打包(Bundling)和转译(Transpilation)能力。

🚀 二、性能实测:Biome vs ESLint + Prettier 真实对比

理论数据不够说服力,让我们用真实项目来实测。我选取了三个不同规模的项目进行对比:

项目规模 文件数 ESLint + Prettier Biome 性能倍数
小型(个人项目) 52 4.2s 0.15s 28x
中型(内部管理系统) 486 12.8s 0.38s 34x
大型(开源组件库) 2,140 38.5s 1.12s 34x

⚠️ 警告: 上述数据基于 M2 MacBook Pro,Node.js v22。你的实际结果可能因硬件和规则配置不同而有所差异,但倍数关系是稳定的。

🏁 快速体验 Biome

安装只需要一行命令:

# 使用 npm 安装
npm install --save-dev --save-exact @biomejs/biome

# 或使用 pnpm
pnpm add -D @biomejs/biome

初始化配置:

# 生成 biome.json 配置文件
npx @biomejs/biome init

生成的 biome.json 配置文件如下:

{
  "$schema": "https://biomejs.dev/schemas/2.0.0/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": {
      "quoteStyle": "single",
      "semicolons": "always"
    }
  }
}

运行检查和格式化:

# 检查代码问题
npx @biomejs/biome check ./src

# 自动修复 + 格式化
npx @biomejs/biome check --write ./src

# 仅格式化
npx @biomejs/biome format --write ./src

# 仅 lint
npx @biomejs/biome lint ./src

🔐 三、从 ESLint + Prettier 迁移:完整实战方案

迁移是大家最关心的部分。直接扔掉所有配置从零开始并不现实——你需要保留团队已经习惯的规则。Biome 提供了官方的迁移工具,但仍需要手动调整。

📋 第一步:使用官方迁移工具

# 从现有 ESLint 和 Prettier 配置迁移
npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write

💡 提示: 迁移工具能处理大约 70-80% 的规则映射,但部分 ESLint 插件规则(如 eslint-plugin-import 的排序规则)需要手动配置到 Biome 的等效规则中。

📋 第二步:处理常见映射差异

这是迁移中最容易踩坑的地方。以下是常见的规则映射对照:

ESLint / Prettier 规则 Biome 等效配置 差异说明
prettier/singleQuote javascript.formatter.quoteStyle: "single" 完全一致
prettier/tabWidth formatter.indentWidth: 2 完全一致
@typescript-eslint/no-unused-vars lint.correctness.noUnusedVariables Biome 默认更严格
eslint-plugin-import/order lint.organizeImports.enabled: true 语法不同但功能等价
prettier/trailingComma javascript.formatter.trailingCommas Biome 2.0 默认 "all"
@typescript-eslint/consistent-type-imports lint.style.useImportType 自动添加 type 关键字

一个常见的迁移坑点是 ESLint 的 no-unused-vars 与 Biome 的 noUnusedVariables 行为差异。ESLint 默认只警告,Biome 在 correctness 分类下会将其视为错误(error)。如果你的项目中有大量故意忽略的未使用变量(比如函数参数),需要这样配置:

{
  "linter": {
    "rules": {
      "correctness": {
        "noUnusedVariables": {
          "level": "warn",
          "options": {
            "ignoreRestSiblings": true,
            "argsIgnorePattern": "^_"
          }
        }
      }
    }
  }
}

📋 第三步:处理 Biome 不支持的规则

Biome 目前不支持所有 ESLint 插件规则,以下是一些尚无原生支持的常见需求和替代方案:

// ❌ Biome 尚不支持的规则
// eslint-plugin-react: jsx-no-target-blank
// eslint-plugin-jsx-a11y: 大部分可访问性规则
// eslint-plugin-testing-library: 测试相关规则

// ✅ 替代方案:在 biome.json 中通过 ignore 排除,
// 然后保留一个精简的 ESLint 配置只跑这些插件

对于这种情况,推荐采用混合策略

// biome.json - 处理 90% 的 lint + format
{
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  }
}
// eslint.config.js - 只保留 Biome 不支持的插件
// eslint.config.js (ESLint Flat Config)
import jsxA11y from 'eslint-plugin-jsx-a11y';
import react from 'eslint-plugin-react';

export default [
  {
    plugins: {
      'jsx-a11y': jsxA11y,
      react,
    },
    rules: {
      // 只保留 Biome 不覆盖的规则
      'jsx-a11y/anchor-is-valid': 'error',
      'react/jsx-no-target-blank': 'error',
    },
  },
];

⚠️ 警告: 混合使用 Biome 和 ESLint 时,务必确保两者不会对同一类规则重复检查,否则会出现矛盾的修复建议。用 biome check --write 之后再跑 ESLint,不要反过来。

📋 第四步:CI/CD 集成

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

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

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

      - name: Biome 检查
        run: biome ci ./src

biome ci 命令是为 CI 环境专门设计的——它同时执行 lint 和 format 检查,但不写入文件,只输出错误。相比 biome check,它的输出更适合 CI 日志解析,且会在发现问题时返回非零退出码。

💡 四、进阶配置:规则分级与 monorepo 适配

🎯 规则分级策略

Biome 的规则分为四个等级,理解它们的定位对团队协作至关重要:

等级 含义 典型规则 建议
correctness 逻辑正确性 noUnusedVariables, noUndeclaredVariables ⚡ 必须开启,CI 报错
suspicious 可疑代码模式 noExplicitAny, noDoubleEquals ✅ 推荐开启
style 代码风格 useImportType, noNonNullAssertion 💡 团队协商
nursery 实验性规则 新增但未稳定的规则 ⚠️ 谨慎使用
{
  "linter": {
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn"
      },
      "style": {
        "useImportType": "error"
      },
      "nursery": {
        "useSortedClasses": "warn"
      }
    }
  }
}

💡 提示: nursery 中的规则会在版本升级时被移入正式分类或删除。如果你在 nursery 中启用了某条规则,建议在升级 Biome 版本时检查该规则的状态。

🏗️ Monorepo 配置

Biome 原生支持 monorepo 场景,可以通过配置覆盖为不同子项目设置不同的规则:

{
  "$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  },
  "linter": {
    "rules": {
      "recommended": true
    }
  },
  "overrides": [
    {
      "include": ["packages/shared/**"],
      "linter": {
        "rules": {
          "correctness": {
            "noUnusedVariables": "error"
          }
        }
      }
    },
    {
      "include": ["packages/legacy/**"],
      "linter": {
        "enabled": false
      },
      "formatter": {
        "enabled": true
      }
    }
  ]
}

这个配置对 packages/shared 启用了严格的未使用变量检查,而对 packages/legacy 只做格式化不做 lint——这在渐进式迁移中非常实用。

🔌 编辑器集成

// .vscode/settings.json
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.organizeImports.biome": "explicit",
    "quickfix.biome": "explicit"
  }
}

安装 VS Code 的 Biome 扩展后,保存文件时会自动格式化并修复可自动修复的 lint 问题。体验与 Prettier + ESLint 的保存格式化一致,但速度肉眼可见地更快。

⚡ 五、常见踩坑与避坑指南

坑 1:规则名称映射错误

ESLint 的规则命名是 plugin-name/rule-name,而 Biome 使用 category.ruleName。直接将 ESLint 规则名粘贴到 biome.json 中不会报错,但也不会生效——Biome 会静默忽略未知规则。

解决办法: 使用 biome migrate eslint --write 自动转换,然后手动检查迁移报告中跳过的规则。

坑 2:formatOnSave 与 ESLint 冲突

如果同时启用了 Biome 和 ESLint 的编辑器扩展,保存时可能触发两次格式化,导致文件内容抖动。

解决办法: 逐步禁用 ESLint 扩展的格式化功能,只保留其 lint 能力:

// .vscode/settings.json
{
  "eslint.format.enable": false,
  "editor.defaultFormatter": "biomejs.biome"
}

坑 3:Tailwind CSS 类名排序

ESLint 生态中有 prettier-plugin-tailwindcss 来自动排序 Tailwind 类名。Biome 的 nursery.useSortedClasses 规则(2.0 新增)可以实现类似功能,但排序逻辑可能与 Tailwind 官方推荐不完全一致。

解决办法: 目前推荐的做法是等待该规则从 nursery 毕业,或者使用 Tailwind 的 Prettier 插件作为后处理步骤。关注 Biome 的 GitHub Issues 获取最新进展。

📊 总结:该不该迁移?

维度 ESLint + Prettier Biome 结论
性能 一般(JS 运行时) 极快(Rust 原生) ✅ Biome 胜
规则覆盖度 极广(插件生态) 中等(快速扩展中) ⚠️ ESLint 胜
配置复杂度 两套配置文件 一个 biome.json ✅ Biome 胜
学习成本 低(文档成熟) 中(生态较新) ⚠️ ESLint 胜
维护负担 高(依赖多) 低(零依赖) ✅ Biome 胜
IDE 支持 极好 好(VS Code 原生) ⚠️ 基本持平

我的建议:

  • 新项目直接用 Biome —— 没有历史包袱,直接享受性能红利
  • 中小型项目推荐迁移 —— 规则需求相对简单,迁移成本低
  • ⚠️ 大型项目渐进式迁移 —— 先从格式化开始,lint 保留 ESLint 处理特有插件规则
  • 重度依赖 ESLint 插件生态的项目暂不迁移 —— 等 Biome 规则覆盖更完善

Biome 代表的不只是一个工具的迭代,而是 JavaScript 工具链从 JavaScript 向 Rust/Go 原生化迁移的大趋势。Vite 背后的 Rolldown(Rust bundler)、oxlint(Rust linter)、SWC(Rust transpiler)都在走同一条路。拥抱 Rust 工具链不是追新,而是顺应前端工程化的必然演进。


🔗 相关工具推荐:

📚 相关文章