2024 年底 Biome 正式发布 v2 版本,标志着 Rust 重写的前端工具链进入成熟阶段。根据 npm 下载量数据,Biome 的周下载量已突破 800 万,GitHub Stars 超过 2 万,成为继 Vite 之后增长最快的前端工具项目。对于还在忍受 ESLint + Prettier 动辄上百行配置文件的开发者来说,Biome v2 提供了一个真正的「开箱即用」替代方案——单一工具同时覆盖 Linting、Formatting 和 Import Sorting,执行速度提升 10-35 倍。
🔧 一、Biome v2 架构解析与核心优势
为什么 ESLint + Prettier 需要被替代?
任何一个使用过 ESLint 9 扁平配置(Flat Config)的开发者都经历过这种痛苦:eslint.config.js 动辄超过 100 行,加上 .prettierrc、.editorconfig、各种 parser 和 plugin 的版本冲突,光是配置就消耗了大量精力。
这不仅仅是「配置繁琐」的问题,更深层的矛盾在于:
- ✅ ESLint 和 Prettier 是两个独立进程,对同一文件要解析两次 AST(抽象语法树)
- ❌ ESLint 的
eslint-config-prettier只是关闭冲突规则,不是真正的集成 - ⚠️ 两个工具的插件生态各自为政,版本升级时经常互相踩坑
Biome 的解法很干脆:用一个 Rust 编写的二进制文件替代整个工具链。它在内部共享 AST,Linting 和 Formatting 只解析一次,天然没有冲突问题。
Biome v2 vs ESLint 9 + Prettier 性能对比
我们在一个包含 500 个 TypeScript 文件、约 15 万行代码的中型项目上做了基准测试:
| 指标 | ESLint 9 + Prettier | Biome v2 | 提升倍数 |
|---|---|---|---|
| 全量 Lint(冷启动) | 12.4s | 0.38s | 32.6x |
| 全量 Format | 5.2s | 0.21s | 24.8x |
| 增量检查(单文件) | 1.8s | 0.04s | 45x |
| CI 管道总耗时 | 28s | 1.2s | 23.3x |
| node_modules 依赖数量 | 47 个 | 0 个 | — |
| 配置文件行数 | ~150 行 | ~25 行 | 6x 精简 |
⚡ 关键结论: Biome 的速度优势不是「快一点」,而是数量级的碾压。对于大型 monorepo 项目,CI 时间从分钟级降到秒级,这直接节省了真金白银的 CI 费用。
v2 的关键新特性
Biome v2 相比 v1 的核心改进包括:
- ✅ GritQL 规则自定义:用类似正则的语法编写自定义 Lint 规则,不再需要写 JavaScript 插件
- ✅ Project-Level 配置继承:支持 monorepo 中每个子包独立配置
- ✅ 增强的 JSX/Angular/Vue 支持:从 JavaScript-only 扩展到主流框架
- ✅ Import Sorting 内置:替代
eslint-plugin-import和prettier-plugin-organize-imports
🚀 二、实战迁移:从 ESLint + Prettier 到 Biome v2
第一步:安装与初始化
# 安装 Biome v2(推荐使用 --save-dev)
npm install --save-dev @biomejs/biome@latest
# 初始化配置文件
npx @biomejs/biome init
生成的 biome.json 配置文件非常简洁:
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
}
}
第二步:迁移 ESLint 规则
这是迁移中最关键的一步。Biome 提供了官方迁移命令,但实际项目中大概率需要手动调整。以下是一个典型的 .eslintrc.js 配置映射:
❌ ESLint 9 旧配置(约 80 行):
// eslint.config.js — ESLint 9 扁平配置
import js from "@eslint/js";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import prettierConfig from "eslint-config-prettier";
import importPlugin from "eslint-plugin-import";
export default [
js.configs.recommended,
{
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
parser: tsParser,
parserOptions: { project: "./tsconfig.json" },
},
plugins: { "@typescript-eslint": tsPlugin, import: importPlugin },
rules: {
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": "error",
"import/order": ["error", { "newlines-between": "always" }],
"no-console": ["warn", { allow: ["warn", "error"] }],
},
},
prettierConfig,
];
✅ Biome v2 等价配置(约 25 行):
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error",
"useImportExtensions": "off"
},
"style": {
"noUnusedTemplateLiteral": "error",
"useConsistentTypeImports": "error"
},
"suspicious": {
"noExplicitAny": "warn"
}
}
},
"organizeImports": {
"enabled": true
}
}
💡 提示: Biome 的规则分类(
correctness、style、suspicious、nursery)比 ESLint 的插件式组织更清晰。nursery分类下的规则还在实验阶段,生产环境慎用。
第三步:格式化规则迁移
Biome 的 Formatter 和 Prettier 的设计哲学有本质区别。Prettier 追求「有主见的(opinionated)」格式化,刻意减少配置项;Biome 则提供了更细粒度的控制:
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf",
"attributePosition": "auto"
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
}
}
⚠️ 一个真实的坑: Biome 和 Prettier 的格式化结果并非 100% 一致。迁移时建议先用 biome check --write 全量格式化一次,然后通过一次单独的 Git commit 记录格式变更,避免污染代码审查。在 .git-blame-ignore-revs 文件中记录这次 commit,让 git blame 跳过格式化改动:
# .git-blame-ignore-revs
# Biome v2 migration — bulk formatting
a1b2c3d4e5f6789012345678901234567890abcd
第四步:VS Code 集成
// .vscode/settings.json
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"quickfix.biome": "explicit"
}
}
注意要禁用 ESLint 和 Prettier 扩展,否则两个工具会互相覆盖保存时的操作。
💡 三、高级用法与团队落地策略
GritQL 自定义规则
Biome v2 引入了 GritQL(一种类似 AST 模式匹配的查询语言),让自定义 Lint 规则变得非常直观。例如,禁止在项目中使用 moment.js:
// biome.json 中的 overrides
{
"overrides": [
{
"includes": ["**/*.ts", "**/*.tsx"],
"linter": {
"rules": {
"nursery": {
"noRestrictedImports": {
"level": "error",
"options": {
"paths": {
"moment": {
"message": "请使用 date-fns 或 dayjs 替代 moment.js,前者体积小 90%"
}
}
}
}
}
}
}
}
]
}
再比如,强制所有 React 组件使用 function 关键字而非箭头函数:
// GritQL pattern in biome rules
`const $name = ($params) => { $body }` where {
$name <: r"^[A-Z]",
$name <: not contains "handle"
}
📌 记住: GritQL 规则目前还在
nursery阶段,API 可能在小版本间变化。生产项目建议锁定 Biome 版本,不要用^或~。
Monorepo 多包配置
Biome v2 原生支持配置继承,非常适合 Turborepo 或 Nx 管理的 monorepo:
// packages/shared/biome.json — 子包覆盖配置
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"extends": ["../../biome.json"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
}
在根目录 package.json 中配置统一的检查命令:
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"check": "biome check --write --unsafe ."
}
}
CI/CD 集成
在 GitHub Actions 中使用 Biome 的最佳实践:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: "latest"
- name: Run Biome
run: biome ci .
biome ci 命令等价于 biome check + biome format --no-write(只检查不修改),专门用于 CI 环境。如果检查失败,退出码非零,Pipeline 自动中断。
常见踩坑与避坑指南
以下是团队迁移 Biome 过程中最常遇到的问题:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 与 Prettier 格式冲突 | 两个格式化工具并存 | 彻底移除 Prettier,不要共存 |
| VS Code 保存时抖动 | ESLint 和 Biome 同时触发 | 在 .vscode/settings.json 中禁用 ESLint 扩展 |
| 旧规则找不到对应 | Biome 的规则命名体系不同 | 用 npx @biomejs/biome migrate 自动映射 |
| 自定义 ESLint 插件无替代 | Biome 不支持 JS 插件 | 用 GritQL 重写,或用 overrides 配置实现 |
| CI 中偶现格式差异 | 本地和 CI 的 Biome 版本不一致 | 在 biome.json 中锁定版本,或使用 biomejs/setup-biome@v2 |
⚡ 关键结论: 迁移 Biome 不要「渐进式共存」,ESLint + Prettier 和 Biome 的格式化逻辑不同,两者共存必然产生冲突。正确的方式是选一个「大爆炸迁移」的时间窗口,一次性切换。
性能优化技巧
对于超大型项目(1000+ 文件),Biome 仍然可以进一步优化:
# 只检查变更的文件(配合 Git)
biome check $(git diff --name-only --diff-filter=ACM -- '*.ts' '*.tsx')
# 使用 --no-errors-on-unmatched 跳过空匹配
biome check --no-errors-on-unmatched src/
# 指定并行线程数(默认为 CPU 核心数)
BIOME_MAX_THREADS=4 biome check .
💡 提示: Biome 默认使用所有 CPU 核心。在 CI 环境中如果容器资源有限,建议通过环境变量
BIOME_MAX_THREADS限制线程数,避免 OOM(内存溢出)。
✅ 总结与建议
Biome v2 已经不是一个「未来可期」的实验性项目,而是一个经过大规模生产验证的成熟工具链。对于以下场景,强烈推荐迁移:
- ✅ 新项目:直接从 Biome 起步,不装 ESLint 和 Prettier
- ✅ 中小项目(< 500 文件):迁移成本低,收益明显
- ✅ CI 耗时敏感的团队:Biome 能将 Lint + Format 时间从分钟降到秒
- ⚠️ 大型项目(> 2000 文件):建议先在子模块试点,确认规则覆盖率后再全量迁移
- ❌ 深度依赖 ESLint 自定义插件的项目:如果用了大量 JS 编写的自定义规则,迁移成本较高
相关工具推荐:
- 🔧 Biome 官方 Playground — 在线体验 Biome 的 Lint 和 Format 效果
- 🔧 jsjson.com JSON 格式化工具 — 在线格式化和校验 JSON 数据
- 🔧 TypeScript AST Explorer — 理解 Biome 如何解析 JavaScript/TypeScript 代码
- 🔧 Rome 工具链历史 — Biome 的前身项目,了解技术演进脉络
前端工具链正在经历一场 Rust 化的底层革命——Vite 用 Rolldown 替代 Rollup,Biome 替代 ESLint + Prettier,Oxlint 作为独立的高性能 Linter 也在快速发展。对于开发者而言,拥抱这些基于 Rust 的新工具不是赶时髦,而是在工程效率上做出正确的投资。