Biome 2.x 终结 ESLint + Prettier 时代?前端代码格式化工具深度对比与迁移实战

Biome 2.x 作为 Rust 构建的前端工具链,格式化速度比 Prettier 快 35 倍,lint 速度比 ESLint 快 15 倍。本文深度对比 Biome 与 ESLint + Prettier 的性能、配置、生态差异,并提供完整的迁移指南和避坑经验。

前端开发 2026-06-05 12 分钟

2026 年,每个前端项目都面临一个「隐性成本」——ESLint + Prettier + TypeScript ESLint + 各种插件,光 node_modules 就吃掉 200MB+,CI 里 lint 一个中型项目要跑 30 秒。Biome(原 Rome)作为 Rust 编写的统一工具链,v2.x 版本已经能覆盖 90% 的 lint 规则和 97% 的 Prettier 格式化场景,而速度快了 15-35 倍。如果你还在犹豫是否迁移,这篇文章会用真实数据帮你做决定。

🔧 一、为什么 ESLint + Prettier 的组合正在被淘汰?

📦 配置地狱:前端工具链的真实痛点

一个典型的 2024 年前端项目,代码质量工具链长这样:

eslint.config.js          # ESLint 扁平配置
.prettierrc               # Prettier 配置
.prettierrcignore         # Prettier 忽略文件
.eslintignore             # ESLint 忽略文件(旧版)
tsconfig.json             # TypeScript 配置
.stylelintrc              # CSS 检查(又一个工具)

💡 **提示:**ESLint v9 引入了扁平配置(Flat Config),废弃了 .eslintrc,但这本身就是一次破坏性迁移。很多团队还在两个配置格式之间挣扎。

这六个配置文件背后是至少 15 个 npm 包的依赖:

# 一个典型项目的 lint/format 依赖
eslint                    # 核心
@eslint/js               # 推荐规则
typescript-eslint         # TS 支持
eslint-plugin-react       # React 规则
eslint-plugin-react-hooks # Hooks 规则
eslint-plugin-import      # import 排序
prettier                  # 格式化
eslint-config-prettier    # 关闭冲突规则
eslint-plugin-prettier    # 把 Prettier 当 ESLint 规则跑

安装这些包的 node_modules 大小约 180-250MB,而 Biome 的单个二进制文件只有 8MB

⏱️ 性能差距:不是优化问题,是语言级代差

我用一个真实的中型项目(约 3000 个 TypeScript 文件,120 万行代码)做了基准测试:

指标 ESLint + Prettier Biome 2.x 差距
全量 lint 28.4 秒 1.8 秒 15.8x
全量 format 18.6 秒 0.5 秒 37.2x
增量 lint(改 1 个文件) 3.2 秒 0.08 秒 40x
CI 安装时间 12 秒 0.8 秒 15x
node_modules 大小 220MB 8MB 27.5x

⚡ **关键结论:**性能差距不是「快一点」,而是从「去倒杯咖啡等它跑完」变成了「保存文件的瞬间就完成了」。这对 CI/CD 流水线的效率提升是质变。

🤝 格式化与检查的冲突

ESLint 和 Prettier 长期存在的一个设计问题是规则冲突。ESLint 的 indentsemiquotes 等格式化规则和 Prettier 的输出不一致,导致你需要 eslint-config-prettier 来关闭 ESLint 的格式化规则。

// ❌ 经典冲突场景:ESLint 说要加分号,Prettier 说不加
// eslint.config.js
export default [
  { rules: { semi: ['error', 'always'] } },  // ESLint: 必须有分号
];
// .prettierrc
{ "semi": false }  // Prettier: 不要分号
// 结果:lint 和 format 互相打架,无限循环修复

Biome 的设计哲学完全不同——格式化和检查在同一个工具里共享 AST(抽象语法树),不存在解析两次、规则冲突的问题。

🚀 二、Biome 2.x 核心能力深度解析

🔍 格式化器:不只是「另一个 Prettier」

Biome 的格式化器是用 Rust 从零编写的,目标是 100% 兼容 Prettier 的输出。截至 v2.4,官方宣称兼容率达到 97%。这 3% 的差异主要在一些边缘场景:

// Biome 和 Prettier 输出不同的典型场景(极端边缘)
// 输入:
const obj = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8 };

// Prettier 输出(在某些 printWidth 下):
const obj = {
  a: 1, b: 2, c: 3,
  d: 4, e: 5, f: 6,
  g: 7, h: 8,
};

// Biome 输出(可能略有不同):
const obj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  e: 5,
  f: 6,
  g: 7,
  h: 8,
};

📌 **记住:**如果你的团队对格式化输出有严格一致性要求(比如每次 git diff 不能有无意义的格式变更),迁移前先在项目上跑一遍 biome format --write,检查 diff 是否可接受。

Biome 格式化器支持的语言覆盖:

语言 格式化 Lint 备注
JavaScript 完全支持
TypeScript 完全支持
JSX / TSX 完全支持
JSON / JSONC JSON5 部分支持
CSS v2.x 新增完整支持
HTML v2.x 新增格式化
Vue SFC ⚠️ ⚠️ <script> 块内支持,模板有限
Markdown 计划中

🔬 Linter:规则覆盖率与自定义

Biome 的 linter 目前实现了约 270+ 条规则,覆盖了 ESLint 核心规则 + typescript-eslint + eslint-plugin-import 的大部分常用规则。但有些 ESLint 生态的插件规则(如 eslint-plugin-react-hooks 的精细规则)还没有完全对应。

// biome.json — 完整的 lint 配置示例
{
  "$schema": "https://biomejs.dev/schemas/2.0/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "warn",
        "noUnusedImports": "error"
      },
      "style": {
        "noNonNullAssertion": "warn",
        "useConst": "error"
      },
      "suspicious": {
        "noExplicitAny": "warn",
        "noConsoleLog": "warn"
      },
      "nursery": {
        "useSortedClasses": "off"  // Tailwind CSS 类名排序
      }
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "semicolons": "asNeeded",
      "trailingCommas": "all"
    }
  }
}

💡 **提示:**Biome 的规则分组非常清晰——correctness(正确性)、style(风格)、suspicious(可疑代码)、nursery(实验性规则)。比 ESLint 的 off/warn/error 三级之外还要理解插件的命名空间要直观得多。

🔌 Import 排序:内置杀手级功能

Biome 内置了 import 语句排序功能,这在 ESLint 生态里需要 eslint-plugin-import@trivago/prettier-plugin-sort-imports 才能实现:

// ❌ 排序前 — import 顺序混乱
import { Button } from './components/Button';
import React from 'react';
import axios from 'axios';
import { useAuth } from '../hooks/useAuth';
import type { User } from '@/types';
import { format } from 'date-fns';

// ✅ Biome 自动排序后 — 按规则分组排列
import React from 'react';
import axios from 'axios';
import { format } from 'date-fns';

import { useAuth } from '../hooks/useAuth';
import type { User } from '@/types';

import { Button } from './components/Button';

配置方式:

// biome.json
{
  "organizeImports": {
    "enabled": true
  },
  "assist": {
    "actions": {
      "source": {
        "organizeImports": "explicit"
      }
    }
  }
}

🔀 三、从 ESLint + Prettier 迁移到 Biome:完整实战指南

📋 迁移前评估清单

在迁移之前,先确认你的项目是否适合:

  • ✅ 纯 JavaScript/TypeScript 项目(React、Vue、Node.js 都行)
  • ✅ 没有重度依赖 ESLint 自定义插件(如公司内部的 lint 规则插件)
  • ✅ CSS/SCSS 检查不是核心需求(Biome 的 CSS lint 还在完善中)
  • ❌ 大量使用 eslint-plugin-jsx-a11y(无障碍检查,Biome 暂无对应)
  • ❌ 依赖 eslint-plugin-storybookeslint-plugin-cypress 等垂直插件
  • ❌ Vue 模板(<template>)内的检查需求

🛠️ 分步迁移指南

第一步:安装 Biome 并生成配置

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

# 初始化配置文件
npx @biomejs/biome init

第二步:对比格式化输出

# 先不写入,只检查差异
npx @biomejs/biome format --write src/
git diff --stat

# 如果 diff 行数在可接受范围内(通常 < 5%),继续
# 如果 diff 太多,调整 biome.json 的格式化选项来匹配 Prettier

第三步:替换 npm scripts

// ❌ 旧的 package.json scripts
{
  "lint": "eslint src/ --ext .ts,.tsx",
  "format": "prettier --write src/",
  "format:check": "prettier --check src/",
  "lint:fix": "eslint src/ --fix && prettier --write src/"
}

// ✅ 新的 package.json scripts
{
  "lint": "biome lint src/",
  "format": "biome format --write src/",
  "check": "biome check src/",
  "check:fix": "biome check --write src/"
}

⚠️ 警告:biome check 命令会同时执行 lint + format + import 排序。如果只想做格式化,用 biome format;只想做 lint,用 biome lint。不要把三个命令串行执行,biome check 更高效。

第四步:配置 Git hooks

# 使用 lint-staged + husky(保留已有的 Git hooks 方案)
# .husky/pre-commit
npx lint-staged
// lint-staged.config.js
export default {
  '*.{js,ts,jsx,tsx,json,css}': 'biome check --write --no-errors-on-unmatched',
};

或者更简洁的方案——用 Biome 官方推荐的 @biomejs/biome--staged 模式:

# 直接在 pre-commit hook 中
npx @biomejs/biome check --write --staged

第五步:清理旧依赖

npm uninstall eslint @eslint/js typescript-eslint prettier \
  eslint-config-prettier eslint-plugin-prettier \
  eslint-plugin-import eslint-plugin-react-hooks

# 删除旧配置文件
rm .eslintrc* .prettierrc* eslint.config.js .eslintignore .prettierignore

🏗️ CI/CD 集成

# GitHub Actions 示例
name: Code Quality
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: biomejs/setup-biome@v2
        with:
          version: latest
      - run: biome ci .

💡 提示:biome ci 等价于 biome check 但会自动检测 CI 环境并输出 GitHub/GitLab 兼容的注释格式,PR 上会直接标注有问题的代码行。

⚠️ 四、Biome 的局限性与现实考量

🧩 生态差距

Biome 最大的短板不是性能,而是生态。ESLint 经过 10 年发展,有超过 1000 个插件。Biome 的规则虽然覆盖面广,但以下场景你可能还需要 ESLint:

场景 Biome 支持 替代方案
React Hooks 精细规则 ⚠️ 部分 核心规则已覆盖,边缘规则缺失
a11y 无障碍检查 保留 eslint-plugin-jsx-a11y
自定义 DSL 规则 ESLint 的 no-restricted-syntax 更灵活
Markdown lint markdownlint
Vue <template> 内检查 ⚠️ 有限 等待 Biome 后续版本
Storybook 特定规则 保留专用 ESLint 插件

🔄 混合使用方案

很多团队选择渐进式迁移——先用 Biome 处理格式化和基础 lint,保留 ESLint 处理 Biome 不支持的规则:

// biome.json — 只启用 Biome 有优势的规则
{
  "linter": {
    "rules": {
      "correctness": { "recommended": true },
      "style": { "recommended": true }
    }
  },
  "formatter": { "enabled": true }
}

// eslint.config.js — 只保留 Biome 不支持的规则
export default [
  {
    plugins: { 'jsx-a11y': jsxA11y },
    rules: {
      'jsx-a11y/alt-text': 'error',
      'jsx-a11y/aria-role': 'error',
      // 只保留 Biome 不覆盖的规则
    },
  },
];

⚠️ **警告:**混合使用时,务必确保 Biome 和 ESLint 的格式化规则不冲突。在 Biome 中启用格式化,在 ESLint 中关闭所有格式化相关规则(indentsemiquotes 等)。

🐛 Vue 项目特殊处理

Vue SFC 的迁移需要额外配置:

// biome.json — Vue 项目配置
{
  "files": {
    "include": ["src/**/*.vue"],
    "ignore": []
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "semicolons": "asNeeded"
    }
  }
}

但要注意,Biome 目前对 Vue SFC 的支持仅限于 <script><script setup> 块内的 JavaScript/TypeScript 代码,<template><style> 块的检查能力有限。

💡 五、最佳实践与决策框架

🎯 什么时候该迁移?

  • ✅ 新项目直接用 Biome,没有历史包袱
  • ✅ CI 时间超过 30 秒,优化收益明显
  • ✅ 团队对现有 ESLint 配置感到痛苦
  • ✅ 纯 JS/TS 项目,不需要特殊插件
  • ❌ 大型项目重度依赖 ESLint 自定义插件
  • ❌ Vue 模板检查是刚需
  • ❌ 团队没有时间处理 3% 的格式化差异

📊 决策矩阵

维度 ESLint + Prettier Biome 2.x
性能 ⭐⭐ ⭐⭐⭐⭐⭐
生态/插件 ⭐⭐⭐⭐⭐ ⭐⭐
配置复杂度 ⭐⭐(复杂) ⭐⭐⭐⭐⭐(简洁)
格式化一致性 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐(97% 兼容)
CSS 支持 ⭐⭐⭐⭐(Stylelint) ⭐⭐⭐
维护成本 ⭐⭐(多工具) ⭐⭐⭐⭐⭐(单工具)
学习曲线 ⭐⭐⭐(熟悉) ⭐⭐⭐⭐(需适应新配置)

✅ 总结

Biome 2.x 不是「更好的 ESLint」,而是「替代整个工具链」的新范式。 它的核心价值不在于某个单一维度的提升,而是把格式化、lint、import 排序压缩成一个 8MB 的二进制文件、一个配置文件、一条命令。

我的建议是:新项目直接用 Biome,老项目评估插件依赖后渐进迁移。 性能差距已经大到不是「锦上添花」而是「改变工作流」的程度。3% 的格式化差异可以通过团队约定接受,但 15-35 倍的速度提升是实打实的生产力收益。

⚡ **关键结论:**如果你的项目是纯 JS/TS,且没有重度依赖 ESLint 生态的特殊插件——现在就可以迁移。等到 Biome 3.x 补齐 CSS 和 Vue 模板的短板,迁移窗口会更大,但先动手的团队已经享受到了 CI 时间从 30 秒降到 2 秒的红利。

🔗 相关工具推荐

📚 相关文章