0. 🐌 迁移背景
eslint / format 太慢,每次 commit 都要等较长时间。Rust 凭借其性能优势大火,能否将其融入我们的开发过程,提升前端的开发“幸福感”?答案是肯定的。
biome vs oxlint
本文使用 biome v1.9.4,如果你的项目是 utils 即没有样式且仅需要 lint 强烈推荐 oxc,否则 biome,当然最推荐的是二者结合。
- biome 同时支持 lint 和 format,其目标是JS 系列(即
[m|c][t]js[x]
)和 css less,不支持 scss,故可替换 eslint/stylelint/prettier(biome 最大的卖点是 format,采用 CST 故即使语法错误也能 format 并且添加必要元素比如括号成正确格式,其次 96%+ 契合 prettier 毕竟赢得过 prettier 的大奖)。 - oxc 极致性能 🚀:但仅支持 lint JS 系列、vue 和 astro svelte script 部分,不支持样式。format 支持中。
- 二者都不支持 eslint 或 stylelint 插件,如果你要检测 js 或 css 的兼容性仍然需要 eslint 和 stylelint。最新消息 2025-6-13 oxlint v1 Roadmap 列出会支持eslint 插件和自定义 lint 规则。
- Rules 对比:biome 200 条,而 oxlint 支持超过 500 条规则,数量和性能目前无人能比,包括所有 ESLint 规则、TypeScript 规则(不包括类型检查),以及 unicorn、jsdoc、react、react-hooks、jest、import 等插件。此外,Oxlint 还提供了一些独特的规则!
更多区别:Comparison with OXC github.com/biomejs/bio…
术语解释
- lint:检测错误
- format:将一行代码格式化成符合规则样式,比如增加空格以及拆分成多行。
- CST:Concrete Syntax Tree - 保留全部语法细节(括号、分号、注释),错误恢复能力强(可继续解析畸形代码),典型代表 Biome、Prettier、Tree-sitter
- AST:Abstract Syntax Tree - 仅语义关键内容(逻辑结构),错误恢复能力 弱(遇到错误可能终止解析),典型代表 OXC、Babel、TypeScript。
特性 AST CST 保留的细节 仅语义关键内容(逻辑结构) 全部语法细节(括号、分号、注释) 错误恢复能力 弱(遇到错误可能终止解析) 强(可继续解析畸形代码) 适用场景 编译器、类型检查 格式化、Lint 工具 性能 更高(结构更简单) 稍低(存储更多信息) 工具示例 OXC、Babel、TypeScript Biome、Prettier、Tree-sitter 关于 CST 和 AST 的区别以及为何 biome 和 OXC 选择不一见 CST vs AST 以及 biome 和 Oxc 各自的选择理由。
1. 📦 安装
pnpm add -D @biomejs/biome
2. ✈️ 迁移 eslint 和 prettier
如果你是新项目直接 pnpx biome init --jsonc
。如果需要迁移则
biome migrate eslint --write
biome migrate prettier --write
迁移之前需要执行 init 确保
biome.json[c]
存在。如果需要迁移从 eslint 启发而来的规则可以加
--include-inspired
。
pnpx biome init
pnpx biome init
// biome.json
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": []
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}
我的项目虽然已经有了 eslint 但是个人觉得 biome 默认规则已经足够优秀,故仅选择迁移 prettier。
已有 .prettierignore:
coverage
public
dist
pnpm-lock.yaml
和 .prettierrc.cjs:
/** @format */
/** @type {import("prettier").Config} */
module.exports = {
semi: false,
tabWidth: 2,
jsxSingleQuote: true,
bracketSpacing: true,
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
proseWrap: 'never',
endOfLine: 'lf',
singleAttributePerLine: true,
}
biome migrate prettier --write
迁移后 biome.json 修改如下(linter 对应 eslint、formatter 对应 prettier):
// biome.json
{
"formatter": {
"enabled": true,
- "indentStyle": "tab"
+ "useEditorconfig": true,
+ "formatWithErrors": false,
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineEnding": "lf",
+ "lineWidth": 100,
+ "attributePosition": "auto",
+ "bracketSpacing": true,
+ "ignore": ["**/coverage", "**/public", "**/dist", "**/pnpm-lock.yaml"]
},
"organizeImports": {
"enabled": true
},
"javascript": {
"formatter": {
- "quoteStyle": "double"
+ "jsxQuoteStyle": "single",
+ "quoteProperties": "asNeeded",
+ "trailingCommas": "all",
+ "semicolons": "asNeeded",
+ "arrowParentheses": "always",
+ "bracketSameLine": false,
+ "quoteStyle": "single",
+ "attributePosition": "auto",
+ "bracketSpacing": true
}
}
}
修改 lint 和 lint:fix
package.json
"lint": "biome lint && tsc --noEmit",
"lint:fix": "biome lint --write --unsafe",
"format": "biome format --write --unsafe",
或者使用 lint 和 format 二合一 check:
"lint": "biome lint && tsc --noEmit",
"lint:fix": "biome check --write --unsafe",
--fix
是--write
的 alias
"\n========== Linting ==========": "",
- "lint": "eslint src && tsc --noEmit",
- "lint:fix": "eslint . --fix",
+ "lint": "biome lint && tsc --noEmit",
+ "lint:fix": "biome check --write --unsafe",
3. ✈️ 迁移 lint-staged
biome 1.7 支持 check staged,无需安装 lint-staged。
删除:
"lint-staged": {
"**/*.{js,ts}": [
"eslint --fix"
],
"**/*": "prettier --write --ignore-unknown"
}
新增
scripts: {
"lint-staged": "biome check --staged --fix"
}
确保 ./.husky/pre-commit 有:
pnpm lint-staged # 或 npm run lint-staged。
4. 🧩 VSCode 插件
设置 formatOnSave settings.json
"editor.codeActionsOnSave": {
+ "source.fixAll.biome": "explicit",
+ "source.organizeImports.biome": "explicit",
"source.removeUnused": "explicit",
"source.fixAll.eslint": "explicit"
},
"[jsonc]": {
"editor.formatOnSave": true,
+ "editor.defaultFormatter": "biomejs.biome"
},
- explicit 是指必须按 ctr + s 主动保存才会执行 fix
- 如果发现加了之后一些不支持 import type 老的 ts 项目也会增加 type 导致编译失败。则需要删除
source.fixAll.biome
5. 🚀 性能对比
实际项目
package.json 新增1个字段、新增一个 biome.json 文件 ⏳ 7s → 4s
npm run lint Before ⏳ ~6s → <2s(基本上是 tsc 的时间):
❯ npm run lint
> @neural/utils@1.1.0 lint
> eslint src && tsc --noEmit
\
ts-library-v2 on 🌱 main [⇡] is 📦 v1.1.0 via Node.js v22.7.0 took 6s
After <2s:
❯ time lint
$ biome lint && tsc --noEmit
Checked 19 files in 12ms. No fixes applied.
bun run lint 0.04s user 0.20s system 13% cpu 1.827 total
去除 tsc 纯粹比较
🆚 eslint vs oxlint vs biome lint
业界
Tool | 1,000 JS Files | Memory Usage | Installation Size |
---|---|---|---|
ESLint + Prettier | 45.2 seconds | 1.2 GB | 120 MB |
Biome.js | 8.7 seconds | 280 MB | 35 MB |
实际项目
总时间:2.7s / 667ms(8ms) / 609ms(5ms)
oxlint 和 biome 速度差不多,但是 oxlint 更胜一筹 🏆。下一篇将尝试将 lint 部分迁移到 oxlint。
实验数据:
❯ time bunx eslint src
bun x eslint src 0.01s user 0.20s system 7% cpu 2.700 total
❯ time bunx biome lint src
Checked 16 files in 8ms. No fixes applied.
bun x biome lint src 0.00s user 0.21s system 32% cpu 0.667 total
❯ time bunx oxlint src
Found 0 warnings and 0 errors.
Finished in 5ms on 16 files with 101 rules using 12 threads.
bun x oxlint src 0.03s user 0.23s system 42% cpu 0.609 total
FAQ
- 如何忽略某行代码不让 biome format:
// biome-ignore format: old code formatted by prettier