· biome / eslint / prettier

Biome v2 Review — Prettier+ESLint thay thế được chưa?

Biome v2 lấp các khoảng trống lớn của v1: phân tích đa file, lint nhận biết kiểu không cần tsc, custom rules qua GritQL. Đủ cho stack của bạn không?

Bởi · Cập nhật 1 tháng 6, 2026

2.193 từ · 11 phút đọc

Nếu dự án của bạn thuần TypeScript hoặc JavaScript — một ứng dụng Next.js, một Node API, hay một component library — Biome v2 đã sẵn sàng thay thế Prettier và ESLint ngay hôm nay. Bản nâng cấp v2 xử lý xong các vấn đề còn tồn đọng từ v1: phân tích đa file, bắt lỗi kiểu mà không cần chạy tsc, và hỗ trợ custom rules. Lợi thế tốc độ xuất phát từ kiến trúc, không phải may mắn.

Nếu stack của bạn dùng Vue, Svelte, hoặc Astro trong production, hoặc bạn có nhiều ESLint plugin thực hiện phân tích ngữ nghĩa phức tạp, hãy chờ thêm hai đến bốn quý nữa. Tính năng đang được phát triển — chưa ổn định cho những trường hợp đó.

Bài này dành cho ai

Các team TypeScript trên monorepo — từ năm đến năm mươi kỹ sư — đang cân nhắc có nên thay Prettier và ESLint bằng một công cụ duy nhất không. Nếu bạn làm một mình trên một package nhỏ, bỏ qua và đọc thẳng phần verdict. Nếu team bạn dùng Vue hay Svelte là framework chính, bắt đầu từ phần lưu ý.

Chúng tôi đã thử nghiệm gì

Biome v2.4.16, phát hành ngày 2026-05-27 — bản stable mới nhất. Các benchmark lấy từ số liệu Biome công bố và các đo lường độc lập đã được xác minh bởi bên thứ ba, có ghi chú phương pháp theo từng số liệu. Khi một con số là tự báo cáo, chúng tôi sẽ nói rõ.

Có gì mới trong Biome v2

Bước nhảy từ v1 lên v2 không chỉ là bản cải tiến nhỏ. Đây là những tính năng thay đổi cách bạn tính toán việc có nên chuyển sang không.

Lint nhận biết kiểu mà không cần TypeScript compiler

Trong v1, các rule cần thông tin kiểu phải chạy tsc — chậm, khó cấu hình, không đáng dùng cho pre-commit hooks. Biome v2 tự xây dựng tầng type inference riêng. Không phải TypeScript compiler đầy đủ, nhưng nó bắt được noFloatingPromises (các async call chưa được xử lý), noMisusedPromises, và các rule liên quan đến async khác. Dữ liệu Biome công bố cho thấy noFloatingPromises của họ bắt được ~75% số trường hợp mà @typescript-eslint/no-floating-promises sẽ cảnh báo.

Đây chưa phải ngang bằng hoàn toàn với typescript-eslint. Nhưng các rule Biome triển khai bao phủ những lỗi async và null-path thực sự gây hại trong production — mà không cần 45 giây chờ type-check. Với hầu hết codebase, vậy là đủ.

Phân tích đa file

Hai rule mới: noImportCyclesnoPrivateImports. Phát hiện dependency vòng tròn giờ xảy ra lúc lint thay vì lúc runtime hay lúc 2 giờ sáng đang xử lý incident. Các rule này không thể có trong mô hình single-file của Biome v1. Với monorepo có shared packages, chỉ noImportCycles thôi đã đáng để chuyển.

Hệ thống plugin GritQL

Custom lint rules giờ đã có thể làm được. GritQL là ngôn ngữ pattern-matching — bạn viết kiểu như js`console.log($msg)` để bắt mọi lệnh console.log và cảnh báo. Các pattern phức tạp hơn có thể xử lý việc giới hạn import từ đường dẫn cụ thể hay yêu cầu hình dạng argument nhất định.

Đây không phải là hệ thống plugin JavaScript AST đầy đủ như ESLint. Các rule cần phân tích scope, type flow, hay trạng thái cross-file không thể viết bằng GritQL hiện tại. Nhưng phần lớn ESLint rule nội bộ tôi thấy ở các team đều là pattern-matching — chặn deprecated API, kiểm tra import, cảnh báo console call. GritQL xử lý được tất cả những điều đó.

Domains

Biome đọc package.json của bạn và tự bật các rule set phù hợp. Dự án React? Rule React bật. Jest trong devDependencies? Rule Jest kích hoạt. Next.js trong dependencies? Rule đặc thù của Next.js chạy. Bạn không cần cấu hình — tất cả được phát hiện tự động từ những gì bạn đã cài.

Import organizer nâng cấp

Import sorter của v1 đã hoạt động ổn. Phiên bản v2 xử lý thêm việc merge import trùng lặp, phân tách đúng các nhóm type/value/side-effect, và hỗ trợ sắp xếp nhóm tùy chỉnh. Điều này loại bỏ lý do cuối cùng để giữ prettier-plugin-organize-imports hay các sort rule của eslint-plugin-import trong stack của bạn.

Hỗ trợ monorepo

"root": false trong file biome.json lồng nhau cho phép từng package kế thừa cấu hình gốc mà không cần reset lại. Đây là vấn đề nghiêm trọng trong v1 — kế thừa cấu hình quá cứng nhắc buộc các team phải copy-paste settings. Một monorepo với mười package giờ có thể có một root config duy nhất cộng với các override theo từng package mà không phải vật lộn với tool.

Hỗ trợ ngôn ngữ nhúng (v2.4)

Biome v2.4 bổ sung khả năng format và lint đúng cho CSS và GraphQL nhúng bên trong các block styled-components và Emotion. Đây là thiếu sót đáng kể với các team React — styled-components là cách tiếp cận CSS-in-JS phổ biến nhất, và việc Biome âm thầm bỏ qua những block đó gây ra sự không đồng nhất về định dạng giữa formatter và code.

Bản phát hành này cũng bổ sung 15 rule HTML accessibility (cho HTML formatting, hiện ở chế độ experimental và tắt theo mặc định).

Vue, Svelte, Astro (v2.3, experimental)

Hỗ trợ này có mặt từ v2.3. Biome team còn ghi nhận các edge case trong cú pháp templating. Coverage chưa đạt mức tương đương với bề mặt JS/TS. Hãy coi đây là beta — hữu ích cho các team muốn thử nghiệm, nhưng chưa ổn định cho production.

Hiệu suất

Những con số Biome công bố là thật — trong điều kiện benchmark của Biome:

Kịch bảnESLint / PrettierBiomeNguồn
Format 171,127 dòng / 2,104 file (i7 1270P)Prettier baselineNhanh hơn 35×Biome (tự báo cáo)
Pre-commit hook, monorepo TS lớn27.2 s1.8 s (15×)Case study bên thứ ba

Con số 35× là benchmark của chính Biome — hãy coi đó là giới hạn trên trong điều kiện gần lý tưởng. Con số 15× pre-commit (giảm 92.6%) đến từ một migration production thực tế có thể xác minh độc lập, không phải fixture tổng hợp.

Trên một TypeScript monorepo cỡ vừa thông thường, trong thực tế kỳ vọng nhanh hơn 8–15×. Lợi ích lớn nhất nằm ở CI và pre-commit hooks, nơi overhead khởi động nguội (Node.js startup, giải quyết ESLint plugin, gọi type-checker) là chi phí chủ yếu. Trên repo mà lint hiện chạy xong trong dưới hai giây, cải thiện có thật nhưng bạn sẽ không cảm nhận được.

Lý do cấu trúc tạo ra khoảng cách này: một binary Rust duy nhất, tận dụng toàn bộ CPU (ESLint mặc định chạy đơn luồng), không có overhead khởi động Node.js, không có chuỗi giải quyết plugin. Khoảng cách đó không thu hẹp khi Biome bổ sung thêm rule.

Độ bao phủ rule và khoảng trống

Danh mụcBiome v2.4.16
Core ESLint recommended~94% các rule thường dùng
typescript-eslint type-awareMột phần — các rule async quan trọng (noFloatingPromises, noMisusedPromises) được bao phủ; rule scope/type-flow thì không
React / JSX~90%+
CSSFormatting + lint cơ bản
Vue / Svelte / AstroExperimental (v2.3+)
HTML formattingExperimental, tắt theo mặc định
MarkdownTrên lộ trình 2026, chưa phát hành
Hệ sinh thái shareable configMỏng hơn so với catalog của ESLint

Hai khoảng trống sẽ thực sự ảnh hưởng đến bạn:

react-hooks/exhaustive-deps: Biome có phiên bản cơ bản. Rule eslint-plugin-react-hooks xử lý phân tích biểu thức dependency phức tạp mà Biome bỏ sót trong một số trường hợp. Nếu bạn áp dụng hooks discipline nghiêm ngặt trên một codebase React lớn, hãy chạy cả hai và so sánh kết quả trước khi xóa ESLint.

Custom rules qua GritQL: Pattern-matching xử lý được hầu hết việc kiểm tra quy ước. Nó không xử lý được các rule cần phân tích ngữ nghĩa đầy đủ — scope chain, type flow, trạng thái cross-file. Nếu bạn duy trì các ESLint plugin nội bộ cho những trường hợp đó, hãy giữ ESLint cho tập hợp đó hoặc chấp nhận giảm coverage.

Xem so sánh Biome vs ESLint chi tiết để có bảng phân tích rule đầy đủ hơn.

Migration

Các lệnh migration chính thức xử lý phần lớn công việc:

npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init

# Import existing configs:
npx @biomejs/biome migrate eslint --write
npx @biomejs/biome migrate prettier --write

# CI check:
npx @biomejs/biome ci .

Trên một monorepo cỡ vừa, dự kiến tổng 1–4 giờ:

  • 30–60 phút — chạy các lệnh, đọc migration report (lệnh migrate xuất ra những gì không thể chuyển đổi; hãy đọc trước khi cho rằng mọi thứ đã xong)
  • 30–90 phút — xử lý các rule chưa được chuyển đổi (cấu hình YAML không được hỗ trợ; file cấu hình JS cần Node.js để chạy, phải chuyển thủ công sang JSON)
  • 30–60 phút — xem xét formatting diff (Biome và Prettier không giống nhau 100% về hành vi — lần format đầu tiên sẽ chạm vào nhiều file; hãy commit riêng phần này)
  • 15–30 phút — bật VCS integration thủ công (Biome không tự phát hiện .gitignore; thêm vcs.enabled = truevcs.useIgnoreFile = true vào biome.json)

Commit formatting diff là noise thuần túy. Commit riêng với message rõ ràng để reviewer có thể bỏ qua khi review các thay đổi logic thực sự.

Để có hướng dẫn đầy đủ hơn bao gồm cài đặt editor, CI, và cấu hình .gitignore, xem Hướng dẫn chuyển từ ESLint và Prettier sang Biome.

Hỗ trợ editor

VS Code extension V3 (tháng 4 năm 2025) bao phủ các trường hợp chính: hỗ trợ multi-root workspace, chế độ single-file cho các file nằm ngoài project biome.json, tự động reload khi thay đổi cấu hình, và format-on-save cho buffer chưa lưu. Tính năng tải binary Biome tích hợp đã bị xóa — hãy cài @biomejs/biome cục bộ cho từng project. Đây cũng là cách đúng đắn; nó gắn phiên bản vào repo thay vì phụ thuộc vào những gì extension đã tải về.

Hỗ trợ JetBrains tồn tại dưới dạng community plugin. Nó hoạt động, nhưng tích hợp rõ ràng kém hoàn thiện hơn VS Code extension. Nếu team bạn chủ yếu dùng IntelliJ hay WebStorm và phụ thuộc vào format-on-save sát sao, hãy dự kiến một khoảng thời gian khó khăn trong quá trình triển khai.

Kết luận

Chuyển ngay nếu:

  • Stack của bạn thuần TypeScript hoặc JavaScript (Next.js, React, Node, Remix)
  • CI lint và format chạy hơn 30 giây và bạn muốn xử lý ngay tuần này
  • Bạn chấp nhận coverage một phần của typescript-eslint type-aware — các lỗi async như noFloatingPromisesnoMisusedPromises được bao phủ, nhưng các rule scope-chain và type-flow thì không
  • Bạn không duy trì ESLint plugin nội bộ đòi hỏi phân tích ngữ nghĩa

Chờ 6–12 tháng nếu:

  • Framework chính của bạn là Vue, Svelte, hoặc Astro (hỗ trợ experimental chưa ổn định cho production)
  • Bạn phụ thuộc nhiều vào các edge case của exhaustive-deps
  • Bạn duy trì các ESLint plugin nội bộ cần phân tích scope-chain hoặc type-flow

Bỏ qua nếu:

  • Bạn cần Markdown formatting (trên lộ trình 2026, chưa phát hành)
  • Bạn dùng hơn mười custom ESLint plugin, một số trong đó cần phân tích ngữ nghĩa ngoài pattern matching

Lưu ý

Benchmark tự báo cáo 35× là giới hạn trên. Phương pháp của Biome minh bạch, nhưng điều kiện thiên về tận dụng parallelism. Tốc độ tăng trong thực tế phụ thuộc vào khối lượng ESLint plugin, số lượng file, và phần cứng của bạn. Ước tính 8–15× cho các project thông thường đến từ các migration đã được báo cáo thực tế, không phải fixture tổng hợp.

Giới hạn của GritQL đối với custom rule phức tạp chưa được kiểm tra toàn diện ở đây. Nếu bạn duy trì các lint plugin nội bộ phức tạp, hãy chạy thử nghiệm trên một package trước khi migrate toàn bộ monorepo.

Vue/Svelte/Astro: “experimental” là nhãn của chính Biome team. Nếu đó là framework chính của bạn, bài đánh giá này chưa phải bức tranh đầy đủ về rủi ro migration của bạn.

Biome miễn phí và mã nguồn mở. Không có chương trình affiliate — không có quan hệ affiliate ở đây.

Tài liệu tham khảo