从 ESLint + Prettier + Stylelint 到 Biome:一次前端代码规范重构实录

在前端工程中,使用ESLint、Prettier和Stylelint等工具可能导致性能问题和配置复杂性。Biome作为新一代工具链,提供了更快的性能和统一的配置体验,能够显著减少代码检查和提交的等待时间。迁移到Biome后,开发效率提升,配置文件数量减少,团队可以更轻松地管理代码规范。尽管Biome尚未完全覆盖Stylelint的所有规则,但对于大多数前端项目来说,其稳定性和速度已足够满足需求。

分类
科技
标签
软件工具golang生活总结

🧩 背景:三套工具的「规约地狱」

在做前端工程化时,我们几乎都经历过这样的「工具链堆叠」:
  • ESLint:语法、规则、最佳实践;
  • Prettier:格式化;
  • Stylelint:样式代码规范;
  • 再加上 husky + lint-staged 提交钩子;
起初一切都还好,但随着项目变大、依赖升级、规则冲突、插件失效、配置重复……
更糟糕的是,这些工具带来的性能负担:
  • 实时代码检查:每次编辑代码后,ESLint 等工具就会在后台运行,给我的 MacBook Air 带来明显的发热和卡顿;
  • 提交等待时间:每次 git commit 都要等待 lint-staged 运行完所有检查,少则几秒,多则十几秒,打断开发节奏;

ESLint 为什么这么慢?

深入研究后,我发现 ESLint 的性能问题并非偶然,而是架构层面的限制:[1]
1. 单线程架构的历史包袱
  • ESLint 从诞生到 2025 年 8 月(v9.34.0)才引入多线程支持,十多年来一直是单线程逐个处理文件
  • 无法充分利用现代多核 CPU,大型项目中浪费了大量计算资源
2. JavaScript/Node.js 的性能天花板
  • 作为解释型语言,JavaScript 的运行速度本身就比 Rust、Go 等编译型语言慢数十倍
  • Node.js 的 V8 引擎虽然已经很快,但在 CPU 密集型任务(如 AST 解析)上仍有明显劣势
3. TypeScript 类型检查的「黑洞」
  • typescript-eslint 的类型感知规则需要调用 TypeScript 编译器 API[2]
  • 第一次运行时缓存未生效,可能导致 7 分钟以上的等待时间
  • 即使有缓存,复杂项目依然会出现 100% CPU 占用、8GB+ 内存消耗的情况[3]
4. AST 转换和选择器引擎的低效
  • ESLint 需要将代码解析为抽象语法树(AST),然后用选择器引擎匹配规则[4]
  • 这个过程在 JavaScript 实现中存在大量性能瓶颈,尤其是处理大文件时
5. 默认不启用缓存
  • ESLint 虽然支持 --cache 参数,但默认关闭[5]
  • CI 环境中每次都要完整运行,浪费大量时间
🧠 我开始思考:有没有一个统一的、快速的、零配置的替代方案?
于是我看向了 Biome

🚀 Biome:速度惊人的统一工具链

Biome 是由 Rome 团队重构的新一代前端工具链,它最大的特点就是:快,非常快[1]

为什么选择 Biome?

性能优势:
  • 比 ESLint 快数百倍:在大型项目中,ESLint 冷运行可能需要 7 分钟,而 Biome 只需 1.5 秒以内[1]
  • 比 Prettier 快 35 倍:得益于 Rust 实现,格式化速度是传统工具的数十倍[2]
  • 与 Prettier 97% 兼容:迁移成本极低,几乎无缝切换[2]
  • 实时检查零卡顿:ESLint 在大型项目中经常导致编辑器卡顿,Biome 完全不会[3]
统一体验:
  • Linter(替代 ESLint)
  • Formatter(替代 Prettier)
  • Import Sorter(替代 eslint-plugin-import
  • 一个工具、一个配置、一条命令
开发体验改善:
  • 实时检查不再卡顿,MacBook 机身温度也降下来了
  • Git 提交钩子从十几秒缩短到 1-2 秒
  • 配置文件从 3 个精简为 1 个(biome.json
💡 对于追求开发效率的团队来说,Biome 不仅仅是"够用",而是真正意义上的性能飞跃[2]

🪤 踩坑记录

⚠️ 1. “Suppression comment has no effect”

Biome 会检测无效的 // biome-ignore 注释。
最初我拼错了规则路径(少了 lint/correctness/ 前缀),导致提示:
1Suppression comment has no effect. Remove the suppression or make sure you are suppressing the correct rule. 2
✅ 解决:使用完整路径,例如:
1// biome-ignore lint/correctness/useUniqueElementIds: static id is safe here 2<div id="fixed" /> 3

⚠️ 2. “Some errors were emitted while applying fixes.”

表示 Biome 在自动修复时遇到无法安全修改的内容。
原因通常是复杂语法或冲突的格式化规则。
✅ 解决:
查看命令行详细输出,手动修复有问题的文件,再运行 biome check --write

⚠️ 3. “静态 id 不允许”

Biome 禁止在 JSX 中写死 id="xxx"(规则:useUniqueElementIds)。
目的是防止 React SSR/水合时重复 ID。
✅ 解决:
1import { useId } from "react"; 2 3const id = useId(); 4return <input id={id} />; 5
或局部禁用规则:
1// biome-ignore lint/correctness/useUniqueElementIds: safe for static DOM 2

⚠️ 4. “eslint [ENOENT]”

项目已经不用 ESLint,但 lint-staged 还在调用它
日志长这样:
1[FAILED] eslint [ENOENT] 2husky - pre-commit script failed (code 1) 3
✅ 解决:
删除 .lintstagedrc.mjs,改为在 package.json 中直接配置 Biome。

⚙️ 最终产物:干净的工程配置

1{ 2 "lint-staged": { 3 "**/*.{js,jsx,ts,tsx,css,scss,md,json}": "pnpm exec biome check --write --no-errors-on-unmatched" 4 }, 5 "scripts": { 6 "check": "biome check .", 7 "fix": "biome check --write .", 8 "format": "biome format --write ." 9 } 10} 11
  • 没有 .eslintrc.*
  • 没有 .prettierrc
  • 没有 .stylelintrc
  • 配置文件总量从 3 个缩减为 1 个
提交速度更快,CI 日志更干净。

💡 经验总结

主题
经验总结
性能
Biome 格式化和 lint 速度比 ESLint + Prettier 快约 5-10 倍
兼容性
对 TS / JSX 支持稳定;SCSS/嵌套语法需谨慎
学习成本
低,规则命名清晰、配置统一
工程复杂度
极大简化:一个配置、一个命令、一个依赖
团队落地
推荐从新项目或轻量项目先行试点,再推广

🧭 总结

迁移到 Biome 后,我最大的感受是:
🧹 工程“清爽”了,
🚀 提交钩子更快了,
🧠 心智负担更小了。
虽然它暂时还没完全覆盖 Stylelint 的所有规则,但对于大多数前端项目来说,Biome 已经足够稳定、足够快、足够省心。

下一步计划:
  • 跟踪 Biome 对 SCSS / CSS-in-JS 的支持;
  • 等官方 Stylelint 替代层稳定后,彻底移除 stylelint;
  • biome.json 维护团队统一代码规范。

如果你正在犹豫是否要迁移到 Biome ——
✨ 我建议:大胆试试看,从你最小的项目开始。
你会感受到一个「现代」前端工具该有的样子。

 
 

Follow Me | 关注我

  • 公众号
    • Ball TriangleAnimated representation of three balls
      notion image