I previously wrote an analysis on whether Biome can replace ESLint + Prettier. After several months of full rollout across the team, here is a summary of the complete workflow experience.
Migration Strategy: Incremental Replacement
A big-bang migration is not recommended. Our path:
阶段 1:Biome 作为 formatter 替代 Prettier(风险最低)
阶段 2:Biome 作为 linter,和 ESLint 并行运行
阶段 3:逐步关闭 ESLint 规则,Biome 接管
阶段 4:移除 ESLint + Prettier 依赖
阶段 1:格式化迁移
# 安装 Biome
pnpm add -D @biomejs/biome
# 生成配置
npx @biomejs/biome init
// biome.json
{
"$schema": "https://biomejs.dev/schemas/1.7.0/schema.json",
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"organizeImports": {
"enabled": true
}
}
A key step: format all existing code and commit it in one large commit, to avoid polluting subsequent PRs with diff noise:
npx @biomejs/biome format --write .
git add -A && git commit -m "chore: apply biome formatting to all files"
阶段 2-3:Linter 迁移
// biome.json 补充 linter 配置
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error",
"useExhaustiveDependencies": "error"
},
"suspicious": {
"noExplicitAny": "warn"
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error",
"useTemplate": "error"
},
"complexity": {
"noExcessiveCognitiveComplexity": ["error", { "max": 15 }]
}
}
}
}
ESLint 规则映射表
We maintained a mapping table to ensure nothing was missed:
// eslint-to-biome-mapping.json
{
"react-hooks/exhaustive-deps": "correctness/useExhaustiveDependencies",
"@typescript-eslint/no-unused-vars": "correctness/noUnusedVariables",
"no-unused-vars": "correctness/noUnusedVariables",
"eqeqeq": "suspicious/noDoubleEquals",
"no-console": "suspicious/noConsoleLog",
"prefer-const": "style/useConst"
}
CI 集成
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
biome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: biomejs/setup-biome@v2
with:
version: latest
- run: biome ci .
The biome ci command will:
- Check formatting
- Run lint checks
- Check import ordering
- Block CI on non-zero exit code
Pre-commit Hook
// package.json
{
"scripts": {
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write ."
},
"simple-git-hooks": {
"pre-commit": "pnpm lint"
}
}
Problems Encountered
1. 规则不完全对等
Biome's rules are not 1:1 mapped to ESLint. Some ESLint plugin rules (e.g., certain rules from eslint-plugin-react) are not yet supported by Biome.
Solution: Retain a small number of ESLint rules as a supplement, downgraded to warnings using eslint-plugin-only-warn.
2. ignore 文件差异
Biome uses .biomeignore instead of .eslintignore, with slightly different syntax:
# .biomeignore
dist/
build/
*.min.js
3. IDE 集成
VS Code 的 Biome 扩展比 ESLint 扩展年轻,偶尔会有卡顿。解决方案是重启 LSP server。
团队落地经验
关键:一次格式化提交。不做这一步,每个 PR 都混着格式变更,review 极其痛苦。
CI 必须强制。光靠本地 IDE 提示不够,CI 不通过就无法合并。
团队培训。花了 30 分钟给团队做了个内部分享,重点讲规则含义而不是配置语法。
Summary
- 渐进式迁移:formatter → linter(并行)→ linter(接管)→ 移除旧依赖
- 格式化先做一次大提交,避免 diff 污染
- CI 必须用
biome ci命令强制检查 - 维护 ESLint → Biome 规则映射表,确保不遗漏
- 团队落地速度约 2 周,主要成本在第一次格式化