我用Biome替换ESLint+Prettier在项目上踩了不少坑

被ESLint折磨了大半年,上周终于下定决心换成了Biome。速度是真的飞起,但中间踩的坑也够我喝一壶的。特别是那个Vue项目,差点让我直接回滚。 我们的Vue 3中后台项目,200多个文件,ESLint配了60多条规则,再加Prettier做格式化,CI跑一遍lint+format要两分多钟。组里有人吐槽"提交一次代码等lint等到忘记刚才在改啥"。我当时也没当回事,直到有天晚上debug到凌晨三点,等lint的时间比写代码还长,心态彻底崩了。 那两天正好刷到Biome v2.5.5的发布,511条规则,97%兼容Prettier,Vercel、Cloudflare都在用。我想着反正周末也没事,干脆试试。 手里三个项目:Vue 3中后台(220文件)、React 18 + Next.js 15官网(150文件)、纯Node.js后端(80文件)。打算挨个来。

装是真好装

css 复制代码
npm i -D --save-exact @biomejs/biome
npx @biomejs/biome init

两行命令,生成一个biome.json,改改配置就能跑。第一次biome check ./src,Vue项目甩给我2000多个报错------当时确实慌了一下。但仔细翻了翻,大头是格式问题,真正的lint错误300多条。 先跑format把格式批量修掉:

perl 复制代码
npx @biomejs/biome format --write ./src

几秒钟完事。我用time测了一下,Biome格式化220个文件用了不到1秒,Prettier之前要12秒。看到这个数字我愣了有好几秒,反复跑了三遍确认没看错。

Vue项目:差点劝退

先说最痛的那个坑,因为就是它让我差点放弃。 我们的Vue组件用的是<script setup lang="ts">,之前ESLint通过vue-tsc做类型检查------模板里传错prop类型,vue-tsc能在CI阶段直接拦住。 迁完Biome跑了一遍CI,全绿。我还挺得意,跟同事说"换工具就是爽"。

结果过了两天QA报了一个bug:某个表单组件传了错误的prop类型,页面渲染异常。我一查,这个错误以前vue-tsc会直接报错的,现在Biome根本没拦到。 原因是Biome的lint只在语法层面做检查,它不懂类型推导。那种需要类型信息才能判断的问题------比如你传了string给期望number的prop------它完全看不出来。 当时真的想骂人。全绿了两天,以为万事大吉了,结果漏了个生产bug。 后来的解决方案是保留vue-tsc单独跑类型检查,Biome只管lint和format:

json 复制代码
{
  "lint": "biome check ./src",
  "format": "biome format --write ./src",
  "type-check": "vue-tsc --noEmit",
  "ci": "npm run type-check && npm run lint"
}

不是那么"all-in-one",但至少不出事。Next.js那边倒没这个问题,tsc在build阶段已经做了类型检查。

ESLint自定义规则:这个是真没辙

Vue项目有一套自定义ESLint规则------禁止组件里直接操作DOM、限制ref的使用方式、强制某些import顺序。有的是eslint-plugin-vue扩展的,有的是自己写的。 Biome不支持自定义规则。官方文档白纸黑字写着,我当时心存侥幸想去搜搜有没有plugin方案,翻了一圈GitHub issues,确认没有。 最后搞了个很土的折中方案:通用规则迁到Biome(需要做规则名映射,比如ESLint的no-unused-vars对应Biome的noExplicitAny),自定义规则写了个简陋的脚本在CI里单独跑------就是正则加grep,不优雅但能用。

json 复制代码
{
  "linter": {
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "error",
        "noUnusedImports": "error"
      },
      "suspicious": {
        "noExplicitAny": "error"
      },
      "style": {
        "useConst": "error",
        "noNonNullAssertion": "warn"
      }
    }
  }
}

Node.js后端那个项目就好多了,没多少自定义规则,no-unused-varsno-consoleeqeqeq这些Biome全都原生支持,半小时搞定。

Prettier那3%的不兼容

说实话,3%听起来不多,但对格式有洁癖的人来说体感远不止3%。 Vue项目里有段CSS,注释在属性之间,Biome格式化之后把注释位置挪了。Prettier会保持注释在gappadding之间,Biome挪到了padding后面。同事review的时候直接问"谁把我注释挪了"。 React项目里更烦------JSX里有一段多行注释解释为什么组件顺序不能改,Prettier会把注释块对齐到特定位置,Biome保持原样。视觉上差几个空格,但代码review的时候看着就是"不舒服"。 我一开始还想着写个脚本强制对齐注释,搞了半小时发现越搞越乱,最后放弃了。在biome.json里把格式冲突的几个文件加到files.ignore,眼不见为净。

IDE那边也有个小插曲

换完Biome忘了改VS Code的defaultFormatter,结果保存文件的时候Biome和Prettier来回打架------Biome改一遍,Prettier又改回来,git status一堆无意义的diff。排查了半小时才反应过来。

json 复制代码
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.codeActionsOnSave": {
    "source.organizeImports.biome": "explicit"
  }
}

改了配置就没事了。另外Biome的LSP在v2.5.3之前偶尔会卡死,v2.5.5修了这个bug(changelog里提到了issue #10845),升级到最新就稳了。

速度到底有多离谱

跑了三天测下来的数据,环境是MacBook Pro M4、32GB内存: Vue中后台(220文件):全量lint从40多秒降到1秒出头,format从12秒降到不到1秒。单文件检查从将近2秒变成0.03秒,体感就是------点保存的瞬间就已经check完了。 React官网(150文件):全量lint从28秒降到不到1秒。 Node.js后端(80文件):全量lint从11秒降到半秒以内。 CI pipeline变化最大。Vue项目从3分多钟降到1分出头,lint+format环节从2分多钟缩到10秒以内。省出来的时间主要在TypeScript类型检查和其他步骤上------那些Biome管不了的部分。 node_modules体积也轻了,三个项目平均减少了30-40MB。eslint、prettier和一堆插件全部卸掉了,清清爽爽。

最终配置

Vue项目的biome.json完整版(其他两个更简单):

bash 复制代码
{
  "$schema": "https://biomejs.dev/schema.json",
  "files": {
    "ignore": ["dist/**", "node_modules/**", "src/legacy/**"]
  },
  "organizeImports": { "enabled": true },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "correctness": {
        "noUnusedVariables": "error",
        "noUnusedImports": "error"
      },
      "suspicious": { "noExplicitAny": "error" },
      "style": {
        "useConst": "error",
        "noNonNullAssertion": "warn",
        "useImportType": "error"
      },
      "nursery": {
        "useSortedClasses": {
          "level": "warn",
          "options": { "functions": ["cn", "clsx"] }
        }
      }
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2,
    "lineWidth": 100
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "single",
      "semicolons": "always",
      "trailingCommas": "all"
    }
  },
  "css": { "formatter": { "enabled": true } }
}

src/legacy/**被ignore了------两年前的老代码,格式惨不忍睹,暂时不想动。

哪些情况别急着换

重度依赖ESLint自定义插件的,别换。你公司自己写的eslint-plugin,Biome替代不了。 对格式有极其严格独特要求的,慎重。如果你有一份100行的.prettierrc,那3%的不兼容会让你很难受。 项目里混合了Biome不支持的语言的,也得考虑。虽然JS/TS/JSON/HTML/CSS/GraphQL都支持了,但.vue模板里的深度检查它还做不了。 但如果只是新项目或者对CI速度有刚需的老项目,我觉得值得试。对我来说,自定义规则的麻烦和不兼容的那些小细节,在30多倍的速度提升面前,都不是事。我选Biome。

相关推荐
Yeauty1 小时前
2026 年在 Rust 里处理音视频,该走哪条路?
rust·ffmpeg·音视频·视频
Revolution6117 小时前
页面更新后为什么出现 Loading chunk failed:旧页面如何请求了已删除的构建产物
前端·面试·前端工程化
TDengine (老段)20 小时前
TDengine Go 与 Rust 连接器 — 高性能异步访问
大数据·数据库·物联网·golang·rust·时序数据库·tdengine
魔力女仆1 天前
【RUST AI】把 TTS 搬进浏览器:kokoroi-rs 的 WASM 实践
人工智能·rust·wasm
米尔的可达鸭1 天前
UDP 通信深度实验:从 Windows FastPath 到 ICMP 端口不可达的完整排查
windows·websocket·网络协议·rust·udp·wireshark·tcpdump
Revolution611 天前
首屏变慢后,应该先查资源下载、脚本执行还是接口请求
前端·性能优化·前端工程化
jinshw1 天前
自己实现GIS配图软件(二)
前端·后端·rust
行走的陀螺仪1 天前
从 nvm 到 fnm:更快、更省心的 Node.js 版本管理器迁移指南
rust·node.js·nvm·fnm
AINative软件工程1 天前
LLM 应用的 Eval 数据工程实践:Golden Set 构建、版本管理与生产 Trace 回放
llm·测试·前端工程化