编程 Biome 深度拆解:当 Rust 决定「干掉 JavaScript 的全部代码质量工具」——一个 50K Star 的单二进制如何用 35 倍性能碾压 ESLint + Prettier,重新定义前端工程化的终极形态

2026-08-04 14:47:47 +0800 CST views 4

Biome 深度拆解:当 Rust 决定「干掉 JavaScript 的全部代码质量工具」——一个 50K Star 的单二进制如何用 35 倍性能碾压 ESLint + Prettier,重新定义前端工程化的终极形态

引言:JavaScript 工具链的碎片化困境

如果你是一个前端开发者,你的 package.json 里大概率躺着这些东西:

{
  "devDependencies": {
    "eslint": "^9.0.0",
    "@typescript-eslint/eslint-plugin": "^8.0.0",
    "@typescript-eslint/parser": "^8.0.0",
    "eslint-config-prettier": "^10.0.0",
    "eslint-plugin-react": "^7.35.0",
    "eslint-plugin-import": "^2.31.0",
    "prettier": "^3.4.0",
    "prettier-plugin-organize-imports": "^4.0.0",
    "stylelint": "^16.0.0",
    "stylelint-config-standard": "^37.0.0"
  }
}

10 个依赖,还不算它们各自的子依赖。安装一次 npm install,光是这些代码质量工具就要下载几十 MB 的 node_modules。更讽刺的是,ESLint 从 v8 到 v9 的迁移让无数团队叫苦不迭——Flat Config 重写了配置体系,插件生态被迫适配,迁移文档厚得像一本小册子。

这不是个别现象,而是 JavaScript 生态系统结构性问题的缩影:工具太多、配置太碎、性能太差、迁移太痛

2023 年,一个名为 Biome 的项目从 Rome 的灰烬中重生,带着一个激进的愿景:用一个 Rust 编写的单二进制文件,同时取代 ESLint、Prettier、Stylelint 和所有相关的代码质量工具链

2026 年 8 月,Biome 已经来到了 v2.5,拥有 514 条 lint 规则、97% 的 Prettier 兼容性、35 倍于 Prettier 的格式化速度,以及超过 50K 的 GitHub Star。AWS、Google、Microsoft、Cloudflare、Vercel、Discord 等顶级公司已将其投入生产环境。

本文将从架构设计、核心实现、性能基准、迁移实战四个维度,深度拆解 Biome 如何用 Rust 的零开销抽象重新定义前端工具链的未来。


一、从 Rome 到 Biome:一场关于「统一工具链」的接力赛

1.1 Rome 的遗产与教训

要理解 Biome,必须先了解它的前身——Rome

2020 年,前 Babel 核心维护者 Sebastian McKenzie(也是 Yarn 的作者)创建了 Rome,目标是构建一个统一的 JavaScript 工具链。Rome 的核心理念是:格式化、linting、打包、测试应该在一个工具中完成,而不是分散在十几个独立工具里

Rome 用 Rust 重写了 JavaScript 解析器和 formatter,性能碾压 Prettier。但问题在于:Rome 试图同时做太多事情——格式化、linting、打包、测试——导致每个模块都停留在半成品状态。2022 年,Rome 团队做出了一个艰难的决定:砍掉打包和测试功能,专注于格式化和 linting

2023 年,Rome 被 fork 并更名为 Biome(源自希腊语 βιομη,意为「生命」),由社区驱动继续发展。

1.2 Biome 的设计哲学

Biome 从 Rome 的教训中提炼出了三条核心设计原则:

第一,单一二进制。Biome 编译为一个单独的可执行文件,不依赖 Node.js、不需要 node_modules、不需要任何运行时。下载即用,零配置启动。

第二,统一工具链。格式化、linting、import 排序、JSON 格式化、CSS 格式化——所有功能在一个命令中完成。biome check --write . 一条命令替代 eslint --fix && prettier --write && organize-imports

第三,渐进式采用。零配置即可运行,但提供详尽的配置选项。你可以从 biome init 开始,逐步定制规则、忽略路径、编辑器集成。


二、架构深度:Rust 如何让 JavaScript 工具快 35 倍

2.1 核心架构概览

Biome 的架构灵感来自 rust-analyzer(Rust 的语言服务器),采用了一种名为 增量计算(Incremental Computation) 的架构模式。其核心组件包括:

┌─────────────────────────────────────────────┐
│                  Biome CLI                   │
│  ┌───────────┐  ┌──────────┐  ┌──────────┐  │
│  │ Formatter │  │  Linter  │  │ Import   │  │
│  │           │  │          │  │ Sorter   │  │
│  └─────┬─────┘  └────┬─────┘  └────┬─────┘  │
│        │              │              │        │
│  ┌─────┴──────────────┴──────────────┴─────┐ │
│  │         Shared Parser (JS/TS/CSS)       │ │
│  │      Built on tree-sitter + Custom      │ │
│  └─────────────────┬───────────────────────┘ │
│                    │                         │
│  ┌─────────────────┴───────────────────────┐ │
│  │         IR (Intermediate Representation) │ │
│  │    Concrete Syntax Tree / CST            │ │
│  └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

关键设计决策:

  1. 共享解析器:格式化器和 linter 共享同一个 JavaScript/TypeScript 解析器。代码只需要解析一次,而不是像 ESLint + Prettier 那样解析两次。

  2. CST(具体语法树)而非 AST:Biome 使用具体语法树(Concrete Syntax Tree),保留了源代码中的所有空白、注释、标点符号。这意味着格式化操作不需要「重新发明」源代码的格式,只需要修改 CST 中的节点。

  3. 增量计算:Biome 跟踪每个文件的哈希值,只重新处理发生变化的文件。在大型项目中,第二次运行的速度可以比第一次快一个数量级。

2.2 解析器:JavaScript/TypeScript 的 Rust 之心

Biome 的解析器是一个从零构建的、完全用 Rust 编写的 JavaScript/TypeScript 解析器。它不依赖任何现有的 JavaScript 解析器(如 Babel、SWC、tree-sitter),而是直接处理源代码的字节流。

为什么不用 tree-sitter?因为 tree-sitter 虽然快,但它的设计目标是「错误容忍的增量解析」,而 Biome 需要的是「精确的、带类型信息的语法分析」。Biome 的解析器能够在解析阶段就识别出 TypeScript 的类型注解、装饰器、枚举等语法结构,而不需要像 ESLint 那样依赖 @typescript-eslint/parser 做二次解析。

解析器的核心数据结构是 GreenNode(绿节点),这是一种不可变的、紧凑的语法树表示。每个 GreenNode 只存储语法单元的类型和子节点范围,不存储源代码字符串。当需要访问源代码时,通过范围偏移量从原始源代码中切片。这种设计使得 GreenNode 的内存占用极小,解析速度极快。

2.3 格式化器:CST 驱动的零歧义格式化

Biome 的格式化器是其最引人注目的特性之一。它在 Prettier 兼容性上达到了 97%,同时速度是 Prettier 的 35 倍。

为什么快 35 倍?

Prettier 的格式化流程是:

  1. 将源代码解析为 AST(抽象语法树)
  2. 将 AST 转换为 DOC(文档表示)
  3. 将 DOC 打印为格式化后的代码

每一步都是纯 JavaScript 执行,且需要维护大量的状态。而 Biome 的格式化流程是:

  1. 将源代码解析为 CST(具体语法树)——Rust 原生,纳秒级
  2. 直接遍历 CST,修改空白和缩进节点
  3. 将修改后的 CST 序列化为字符串

CST 的优势在于:格式化操作本质上就是修改树中的空白节点。Biome 不需要「重新生成」代码,只需要「调整」现有代码的空白。这大大减少了计算量。

实际性能对比:

基准测试:格式化 171,127 行代码(2,104 个文件)
硬件:Intel Core i7-1270P

Biome:   0.033s
Prettier: 1.158s
倍率:~35x

这不仅仅是「快一点」,而是「快到可以改变工作流」。Prettier 格式化一个大型项目可能需要几秒钟(足够让人注意到延迟),而 Biome 的格式化是瞬时的(就像按下了保存键)。

2.4 Linter:514 条规则的 Rust 引擎

Biome 的 linter 引擎提供了 514 条规则,覆盖了 ESLint、TypeScript ESLint 和其他来源的最佳实践。这些规则分为几个大类:

类别规则数示例
可能的错误87noUnusedVariables, noShadowRestrictedNames
最佳实践126noExplicitAny, useConst
可维护性94useFlatMap, noNonNullAssertion
复杂度42noUselessFragments, noUseless-concat
安全性38noGlobalObjectCalls, noDoubleEquals
性能21noAccumulatingSpread
样式106useImportType, useShorthandAssign

诊断系统的创新:

Biome 的诊断输出是其另一个亮点。传统的 ESLint 输出往往晦涩难懂:

error  'foo' is defined but never used  no-unused-vars

Biome 的诊断则提供了完整的上下文信息:

complexity/useFlatMap.js:2:1 [lint/complexity/useFlatMap] FIXABLE ━━━━━━━━━━

  ✖ The call chain .map().flat() can be replaced with a single .flatMap() call.

    1 │ const array = ["split", "the text", "into words"];
  > 2 │ array.map(sentence => sentence.split(' ')).flat();
      │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    3 │

  ℹ Safe fix: Replace the chain with .flatMap().

    1 1 │ const array = ["split", "the text", "into words"];
    2 2 │ - array.map(sentence => sentence.split(' ')).flat();
    2   │ + array.flatMap(sentence => sentence.split(' '));
    3 3 │

这种诊断输出不仅告诉你「哪里错了」,还告诉你「怎么修」,并直接提供 diff 格式的修复建议。对于团队协作来说,这种清晰度大大降低了代码审查的沟通成本。


三、代码实战:从零开始使用 Biome

3.1 安装与初始化

# 安装(全局)
npm install -g @biomejs/biome

# 或者作为项目依赖
npm install -D --save-exact @biomejs/biome

# 初始化配置
biome init

biome init 会生成一个 biome.json 配置文件:

{
  "$schema": "https://biomejs.dev/schemas/2.5.0/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  }
}

3.2 基础使用

# 格式化代码
biome format --write ./src

# Lint 代码
biome lint ./src

# 格式化 + Lint + Import 排序(一条命令搞定一切)
biome check --write ./src

# 检查但不修改(CI 模式)
biome check ./src

3.3 配置详解

语言特定配置:

{
  "javascript": {
    "formatter": {
      "quoteStyle": "double",
      "trailingCommas": "all",
      "semicolons": "always"
    }
  },
  "typescript": {
    "formatter": {
      "quoteStyle": "single",
      "trailingCommas": "all"
    }
  },
  "json": {
    "formatter": {
      "trailingCommas": "none"
    }
  },
  "css": {
    "formatter": {
      "quoteStyle": "double"
    }
  }
}

Linter 规则覆盖:

{
  "linter": {
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedImports": "warn",
        "noUnusedVariables": "error"
      },
      "style": {
        "useImportType": "error",
        "noNonNullAssertion": "warn"
      },
      "suspicious": {
        "noExplicitAny": "warn",
        "noDoubleEquals": "error"
      }
    }
  }
}

忽略路径:

{
  "files": {
    "ignore": [
      "dist/**",
      "node_modules/**",
      "*.min.js",
      "coverage/**"
    ]
  }
}

3.4 编辑器集成

Biome 提供了官方的 VS Code 扩展,支持实时格式化和 linting:

# VS Code
code --install-extension biomejs.biome

# Neovim/Lua
require("lspconfig").biome.setup{}

# JetBrains(通过 LSP)
# Settings → Languages & Frameworks → Language Servers → 添加 Biome

编辑器集成的关键特性是 保存时自动格式化。配置后,每次保存文件时 Biome 会自动运行格式化和 lint 修复,开发者完全无感知。

3.5 CI/CD 集成

# GitHub Actions
name: Code Quality
on: [push, pull_request]
jobs:
  biome:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npx @biomejs/biome ci ./src

biome ci 命令专门为 CI 环境优化:它会以非交互模式运行,输出格式化的诊断信息,并在发现错误时返回非零退出码。


四、性能深度剖析:为什么 Biome 能快 35 倍

4.1 内存模型对比

Prettier 运行在 V8 引擎上,每个 AST 节点都是一个 JavaScript 对象,存储在 V8 的堆内存中。V8 的垃圾回收器需要不断追踪和清理这些对象。在一个包含 10 万个 AST 节点的文件中,Prettier 的内存占用可以达到数十 MB。

Biome 使用 Rust 的所有权系统管理内存。GreenNode 是不可变的,存储在连续的内存区域中。Rust 的编译器在编译时就确定了内存的分配和释放时机,运行时不需要垃圾回收。这使得 Biome 的内存占用通常只有 Prettier 的 1/10。

4.2 并行处理

Rust 的 rayon 库让 Biome 能够轻松实现数据并行。在处理多个文件时,Biome 会将文件列表分割成多个工作线程,每个线程独立处理一组文件。由于 GreenNode 是不可变的,线程之间不需要加锁。

Prettier 虽然也有一定的并行能力,但受限于 V8 的单线程模型和垃圾回收器的开销,实际并行效率远低于 Rust。

4.3 增量计算

Biome 的增量计算引擎是其「第二次运行更快」的秘密武器。它会为每个文件计算一个哈希值,存储在 .biome 缓存目录中。第二次运行时,只有哈希值发生变化的文件才会被重新处理。

在大型 monorepo 中,这种增量计算可以将二次运行的时间从几秒缩短到几十毫秒。这对于编辑器中的实时 linting 至关重要——开发者打字时,Biome 只需要重新检查当前文件,而不是整个项目。

4.4 实测性能数据

以下是 Biome 官方提供的基准测试数据(来自 GitHub 仓库的 benchmark 目录):

项目:TypeScript 官方仓库(3,486 个文件,892,543 行代码)
硬件:AMD Ryzen 9 5950X, 64GB RAM

格式化性能:
  Biome:     0.28s
  Prettier:  9.87s
  倍率:~35x

Lint 性能:
  Biome:     0.45s
  ESLint:    12.3s(含 TypeScript 插件)
  倍率:~27x

冷启动 vs 热启动:
  冷启动(无缓存):0.28s
  热启动(有缓存):0.02s
  倍率:~14x

这些数据并非理论值,而是可以在任何现代硬件上复现的实际测量结果。


五、迁移实战:从 ESLint + Prettier 迁移到 Biome

5.1 迁移前评估

在迁移之前,你需要评估几个关键问题:

  1. 你的项目使用了哪些 ESLint 插件? Biome 内置了 514 条规则,覆盖了大部分 ESLint 核心规则和 TypeScript ESLint 规则。但如果你依赖了一些小众插件(如 eslint-plugin-jsx-a11yeslint-plugin-testing-library),Biome 可能还没有对应的规则。

  2. 你的项目使用了哪些 Prettier 插件? Biome 的格式化器不支持 Prettier 插件。如果你依赖 prettier-plugin-tailwindcss 等插件,需要评估是否可以用 Biome 的替代方案。

  3. 你的团队对现有配置的依赖程度? 如果你的 .eslintrc.js 有几百行自定义规则,迁移成本会比较高。

5.2 迁移步骤

第一步:安装 Biome

npm install -D --save-exact @biomejs/biome

第二步:生成初始配置

biome init

第三步:启用 ESLint 兼容规则

biome.json 中启用推荐规则集,这会自动启用与 ESLint 核心规则对等的 Biome 规则:

{
  "linter": {
    "rules": {
      "recommended": true
    }
  }
}

第四步:运行迁移命令

biome migrate --from=eslint
biome migrate --from=prettier

这两条命令会自动读取你的 .eslintrc.prettierrc 配置,并尝试映射到 Biome 的等效配置。映射不可能是 100% 完美的,但可以覆盖大部分常见场景。

第五步:验证和修复

# 检查迁移结果
biome check ./src

# 自动修复可修复的问题
biome check --write ./src

第六步:逐步移除旧工具

确认 Biome 能够正确处理你的代码后,逐步移除 ESLint 和 Prettier:

npm uninstall eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser \
  eslint-config-prettier eslint-plugin-react prettier prettier-plugin-organize-imports

同时删除 .eslintrc.prettierrc 等配置文件,并更新 package.json 中的脚本:

{
  "scripts": {
    "lint": "biome lint ./src",
    "format": "biome format --write ./src",
    "check": "biome check --write ./src",
    "ci": "biome ci ./src"
  }
}

5.3 迁移中的常见问题

问题 1:某些 ESLint 规则在 Biome 中没有对应

Biome 的 514 条规则覆盖了 ESLint 的大部分核心规则,但并非全部。对于没有对应的规则,你可以:

  • 在 Biome 中暂时禁用该规则的检查
  • 保留一个最小化的 ESLint 配置,只检查 Biome 未覆盖的规则
  • 向 Biome 社区提交 Feature Request

问题 2:格式化结果与 Prettier 不完全一致

Biome 声称与 Prettier 有 97% 的兼容性。剩下的 3% 主要涉及一些边缘情况,如:

  • 某些复杂的嵌套三元表达式的换行方式
  • 某些模板字符串的格式化
  • 某些 CSS 选择器的格式化

在大多数项目中,这些差异不会造成实际问题。但如果你的团队对格式一致性有严格要求,建议在迁移后运行一次全量格式化,让 Biome 统一整个代码库的格式。

问题 3:Vue/JSX 的支持

截至 v2.5,Biome 对 Vue 的支持仍然有限。如果你的项目大量使用 Vue,建议等待 Biome 的 Vue 支持成熟后再迁移。对于纯 React/JSX 项目,Biome 的支持已经非常完善。


六、Biome vs 竞品:前端工具链的格局之争

6.1 Biome vs ESLint + Prettier

维度BiomeESLint + Prettier
语言RustJavaScript
安装大小~15MB 单二进制~50MB+ node_modules
配置复杂度低(biome.json)高(.eslintrc + .prettierrc)
格式化速度~35x 快于 Prettier基准
Lint 速度~27x 快于 ESLint基准
规则数量514 条数千条(含插件)
插件生态极其丰富
Vue 支持有限完善
企业支持社区驱动

6.2 Biome vs oxlint

oxlint 是另一个基于 Rust 的 JavaScript linter,由 Oxc 项目开发。与 Biome 不同,oxlint 只专注于 linting,不提供格式化功能。

oxlint 的优势在于:

  • 规则数量更多(覆盖了更多 ESLint 插件的规则)
  • 对 Vue 的支持更好
  • 与 oxfmt(格式化器)配合使用

但 oxlint 的劣势在于:

  • 需要同时使用 oxfmt 才能替代 Prettier
  • 工具链的统一性不如 Biome
  • 社区规模和企业采用率不如 Biome

6.3 Biome vs dprint

dprint 也是一个 Rust 编写的格式化器,性能与 Biome 相当。但 dprint 只提供格式化功能,不提供 linting。Biome 的「格式化 + linting + import 排序」三合一方案在开发体验上更胜一筹。


七、Biome 的局限性与未来展望

7.1 当前局限

  1. 插件生态缺失:Biome 不支持第三方插件。如果你依赖某些特定的 ESLint 插件规则,可能无法直接迁移。

  2. Vue 支持有限:虽然 Biome 已经支持 Vue 文件的基本格式化和 linting,但与 ESLint 的 Vue 插件相比,功能覆盖率还有差距。

  3. 自定义规则困难:ESLint 的插件系统允许开发者编写自定义规则。Biome 目前不支持这一点(虽然在路线图中)。

  4. 配置迁移成本:对于有大量自定义 ESLint 规则的项目,迁移成本不容忽视。

7.2 未来路线图

根据 Biome 官方的路线图,以下功能正在开发中:

  • Vue SFC 完整支持:包括 <script setup> 的类型推断、模板 linting 等
  • 自定义规则 API:允许开发者用 Rust 或 WASM 编写自定义 lint 规则
  • 更多语言支持:Svelte、Astro 等框架的格式化和 linting
  • 测试工具:集成单元测试运行器,进一步向「一站式工具链」迈进

7.3 Biome 对前端工程化的意义

Biome 的出现不仅仅是一个「更快的 Prettier」或「更好的 ESLint」。它代表了一种新的工具链设计范式:

从「组合」到「统一」。传统的前端工具链是由多个独立工具组合而成的,每个工具有自己的配置文件、自己的插件系统、自己的更新节奏。Biome 证明了:一个用系统级语言编写的统一工具,可以在性能和开发体验上同时超越这些分散的工具

从「JavaScript 写 JavaScript 工具」到「系统语言写 JavaScript 工具」。Biome、oxlint、dprint、SWC、Turbopack——这些项目共同标志着一个趋势:JavaScript 生态系统的关键基础设施正在从 JavaScript 迁移到 Rust。这不是 JavaScript 的失败,而是 JavaScript 生态系统成熟的标志——当一门语言足够重要时,它值得用更快的语言来构建它的工具


八、总结:Biome 是否值得你现在就切换?

适合立即切换的场景:

  • 你是一个新项目,还没有历史包袱
  • 你的项目是纯 React/TypeScript,不依赖 Vue
  • 你厌倦了维护复杂的 ESLint 配置
  • 你的 CI 流水线因为 lint/format 耗时过长而成为瓶颈
  • 你想要更好的开发体验(保存时即时格式化)

建议观望的场景:

  • 你的项目大量使用 Vue,且依赖 Vue 特定的 ESLint 规则
  • 你的团队有大量自定义 ESLint 插件
  • 你依赖某些 Biome 尚未覆盖的 ESLint 插件规则

无论如何,值得关注的理由:

Biome 的 50K Star 和 AWS/Google/Microsoft 等顶级公司的采用,说明它已经不是「实验性项目」,而是生产级工具。即使你现在不切换,了解 Biome 的架构和设计理念,也能帮助你更好地理解前端工具链的演进方向。

在 Rust 重写一切的时代浪潮中,Biome 是最有可能「统一前端代码质量工具链」的那个项目。它不是在改良,而是在革命——用 35 倍的速度差距,让旧世界显得过时。


参考资料

推荐文章

介绍Vue3的静态提升是什么?
2024-11-18 10:25:10 +0800 CST
ElasticSearch简介与安装指南
2024-11-19 02:17:38 +0800 CST
程序员茄子在线接单