Hướng dẫn đầy đủ: chuyển từ ESLint và Prettier sang Biome
Hai lệnh xử lý hầu hết việc migrate tự động. Bao gồm toàn bộ: cài đặt, rule mapping, editor setup, CI, gỡ cài đặt — và những gap chặn một số team.
Bởi Ethan
2.298 từ · 12 phút đọc
Hai lệnh biome migrate eslint --write và biome migrate prettier --write xử lý hầu hết quá trình migrate tự động. Phần còn lại là phân tích gap — kiểm tra những rule bạn đang dùng mà Biome chưa hỗ trợ. Với hầu hết các project TypeScript, gap này khá nhỏ. Nhưng với các team phụ thuộc vào eslint-plugin-security, no-floating-promises, hay các plugin framework-specific, đây có thể là blocker cứng.
Hướng dẫn này là walkthrough đầy đủ trên Biome 2.4.15 (phát hành 2026-05-09), từ cài đặt đến CI. Thông thường mất khoảng hai giờ với một project tiêu chuẩn. Monorepo lớn có thể mất cả ngày.
Đối tượng phù hợp
Developer TypeScript và JavaScript đang chạy ESLint 8.x hoặc 9.x cùng Prettier 2.x hoặc 3.x, muốn gộp về một công cụ nhanh hơn. Nếu bạn phụ thuộc vào eslint-plugin-security, linting nặng cho Vue/Svelte/Astro, hoặc custom ESLint rules trong production, hãy đọc Khi nào không nên migrate trước — có thể bạn vẫn cần ở lại với ESLint.
Để so sánh chi tiết về tính năng và độ phủ rule trước khi quyết định, xem Biome vs ESLint 2026.
Tại sao lại đổi
Lý do thực tế để chuyển gói gọn trong ba điểm.
Tốc độ. Biome là một binary Rust duy nhất, chạy song song hoàn toàn. ESLint mặc định là single-threaded và cộng thêm overhead khởi động Node.js cho toàn bộ plugin chain. Benchmark độc lập từ BetterStack đo được tốc độ linting nhanh hơn 10–15× trên project 500 file. Case study thực tế từ FireUp.pro ghi nhận pre-commit hook của một monorepo TypeScript lớn giảm từ 27.2s xuống còn 1.8s — cải thiện 15× thời gian thực. Benchmark nội bộ của Biome tuyên bố linting nhanh hơn 56× và formatting nhanh hơn 40× trên 10,000 file; con số này là giới hạn trên tự công bố, chưa được bên thứ ba xác minh.
Một dependency thay cho sáu cái. Setup ESLint + Prettier thông thường cần cài ESLint core, TypeScript parser, @typescript-eslint, ít nhất hai plugin, eslint-config-prettier, và Prettier. Biome thay thế tất cả bằng một package duy nhất.
Config thống nhất. Một file biome.json kiểm soát cả formatting lẫn linting. Không còn phải đối chiếu .eslintrc với .prettierrc. Không còn cần eslint-config-prettier để tắt các conflict formatting.
Yêu cầu trước khi bắt đầu
Trước khi bắt đầu:
- Node.js đã được cài (cần thiết để chạy migration tool; Biome không cần Node lúc runtime)
- ESLint 8.x hoặc 9.x trong project của bạn
- Prettier 2.x hoặc 3.x trong project (tùy chọn — bỏ qua bước migrate Prettier nếu bạn không dùng)
- Config ESLint của bạn không ở định dạng YAML (
.eslintrc.yaml/.eslintrc.yml) — nếu có, hãy chuyển sang JSON trước; xem Bước 2 - Config Prettier của bạn không ở định dạng JavaScript (
.prettierrc.js) — nếu có, chuyển sang.prettierrc.jsontrước
Bước 1: Cài đặt Biome
# npm
npm install --save-dev --save-exact @biomejs/biome
# pnpm
pnpm add --save-dev --save-exact @biomejs/biome
# bun
bun add --dev --exact @biomejs/biome
Cờ --save-exact được Biome khuyến nghị vì output formatting có thể thay đổi giữa các patch version, và bạn muốn CI cho ra kết quả nhất quán. Hãy pin phiên bản.
Sau khi cài xong, khởi tạo config:
npx @biomejs/biome init
# Nếu muốn dùng JSON with comments (JSONC):
npx @biomejs/biome init --jsonc
Lệnh này tạo file biome.json ở root project với các giá trị mặc định hợp lý. Bạn sẽ điền vào ở các bước tiếp theo.
Lỗi thường gặp: nếu npx @biomejs/biome init báo lỗi permissions, kiểm tra xem node_modules/.bin có quyền ghi không. Với monorepo, đảm bảo bạn đang chạy lệnh từ workspace root.
Bước 2: Chuẩn bị config ESLint
biome migrate eslint hỗ trợ .eslintrc.json (bao gồm extends và shared config), flat config file (.js, .cjs, .mjs), và .eslintignore. Không hỗ trợ config dạng YAML.
Nếu config của bạn đang ở YAML, hãy chuyển đổi trước:
# Cần cài yq trước
yq -o=json .eslintrc.yaml > .eslintrc.json
# Xóa file YAML
rm .eslintrc.yaml
Cũng cần chú ý đến các chuỗi extends vòng tròn — config dùng require() để tham chiếu lẫn nhau thành vòng lặp. Migration tool sẽ thất bại với trường hợp này. Hãy flatten config thủ công trước khi chạy migration.
Bước 3: Migrate rules ESLint
biome migrate eslint --write
Lệnh này đọc config ESLint của bạn, chuyển đổi các rule tương thích sang Biome, và ghi kết quả vào biome.json. Chạy từ thư mục chứa config ESLint.
Nếu muốn Biome áp dụng cả các rule “inspired” — rule mà Biome phát triển dựa trên ESLint nhưng không map trực tiếp — thêm --include-inspired:
biome migrate eslint --write --include-inspired
Các inspired rule bao gồm useArrowFunction (từ prefer-arrow-callback), useImportType (từ @typescript-eslint/consistent-type-imports), và useNamingConvention (một tập con của @typescript-eslint/naming-convention). Kiểm tra từng rule trước khi bật — chúng tắt theo mặc định là có lý do.
Sau khi chạy: mở biome.json và kiểm tra phần linter.rules. Migration tool chuyển đổi những gì nó nhận ra và bỏ qua những gì không. So sánh danh sách rule ESLint gốc với nội dung trong biome.json. Rule nào vắng mặt là gap, hoặc là inspired rule cần thêm --include-inspired.
Lỗi thường gặp: nếu lệnh thoát với Cannot read ESLint plugin, đảm bảo Node.js có trong PATH. Tool cần load các plugin trong quá trình migrate, dù Biome không cần Node lúc runtime.
Bước 4: Xác định gap
Không phải mọi ESLint rule đều có tương đương trong Biome. Những rule quan trọng nhất cho TypeScript project:
| ESLint rule | Biome status |
|---|---|
no-unused-vars | ✅ noUnusedVariables |
no-undef | ✅ noUndeclaredVariables |
eqeqeq | ✅ noDoubleEquals |
@typescript-eslint/no-explicit-any | ✅ noExplicitAny |
@typescript-eslint/prefer-optional-chain | ✅ useOptionalChain |
no-shadow | ❌ Không có tương đương |
no-magic-numbers | ❌ Không có tương đương |
@typescript-eslint/no-floating-promises | ⚠️ Coverage một phần qua type-aware linting (v2.0+) — chưa đạt parity đầy đủ với no-floating-promises |
@typescript-eslint/no-misused-promises | ❌ Không có tương đương |
eslint-plugin-security | ❌ Không có tương đương |
Biome v2.0 giới thiệu type-aware linting mà không cần TypeScript compiler, giúp bắt được các trường hợp floating-promise phổ biến nhất. Nhưng parity đầy đủ với no-floating-promises và no-misused-promises vẫn chưa đạt được.
Nếu những rule đó là bắt buộc với team bạn, có hai lựa chọn: giữ ESLint chỉ cho các rule đó (hybrid mode) hoặc chấp nhận gap. Hybrid mode khả thi nhưng đưa lại phần complexity bạn đang cố loại bỏ.
Nguồn: trang rules sources của Biome và tài liệu linter Biome.
Bước 5: Migrate config Prettier
biome migrate prettier --write
Lệnh này đọc .prettierrc.json (hoặc .prettierrc ở định dạng JSON) và ghi các option formatter tương đương vào biome.json.
Bảng mapping đầy đủ:
| Prettier | Biome | Mặc định (Biome) |
|---|---|---|
printWidth | formatter.lineWidth | 80 |
tabWidth | formatter.indentWidth | 2 |
useTabs | formatter.indentStyle | "tab" |
endOfLine | formatter.lineEnding | "lf" |
singleQuote | javascript.formatter.quoteStyle | "double" |
jsxSingleQuote | javascript.formatter.jsxQuoteStyle | "double" |
trailingComma | javascript.formatter.trailingCommas | "all" |
semi | javascript.formatter.semicolons | "always" |
arrowParens | javascript.formatter.arrowParentheses | "always" |
bracketSpacing | javascript.formatter.bracketSpacing | true |
bracketSameLine | javascript.formatter.bracketSameLine | false |
Điểm quan trọng: Biome mặc định dùng tab cho indentation. Nếu .prettierrc của bạn không khai báo useTabs: false tường minh, migration tool có thể đặt formatter.indentStyle: "tab" trong khi bạn mong đợi spaces. Mở biome.json sau khi chạy và xác nhận formatter.indentStyle đúng với ý định.
Lỗi thường gặp: Prettier config dạng JavaScript (.prettierrc.js, .prettierrc.cjs) không được chuyển đổi đáng tin cậy. Hãy chuyển sang .prettierrc.json trước, chạy migration, sau đó xóa file JS config.
Nguồn: Biome reference configuration.
Bước 6: Cập nhật tích hợp editor
VS Code
Cài extension Biome chính thức từ VS Code Marketplace. Thêm vào .vscode/settings.json của workspace để bật format-on-save:
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
"[json]": { "editor.defaultFormatter": "biomejs.biome" }
}
Vấn đề đã biết: VS Code import organizer có một bug được ghi nhận, có thể làm hỏng import graph phức tạp. Bài viết của Kitty Giraudel về migrate monorepo 40 package ghi nhận import organizer “làm hỏng file khi rewrite imports” (tham chiếu GitHub issue #1570). Nếu bạn phụ thuộc vào import sorting, hãy test trên codebase thực trước khi bật. Bạn có thể tắt riêng import sorter trong VS Code settings:
{
"biome.organizeImports": false
}
Ngoài ra: extension VS Code chỉ áp dụng safe fixes tự động. Unsafe fixes — như noVar chuyển var thành const — cần chạy biome check --write --unsafe từ CLI.
JetBrains / WebStorm
Cài Biome plugin từ JetBrains Marketplace (biomejs.biome). Sau khi cài, vào Settings → Languages & Frameworks → JavaScript → Biome và trỏ đến binary local (node_modules/@biomejs/biome/bin/biome). Bật “Run on save” cho formatting.
Bước 7: Cập nhật CI
Thay thế các bước ESLint + Prettier trong CI bằng một lệnh biome ci duy nhất:
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .
biome ci là biến thể non-interactive của biome check. Nó thoát với code khác 0 khi có bất kỳ vi phạm nào và không tự động fix. Action biomejs/setup-biome cache Biome binary để các lần CI sau không cần tải lại.
Pre-commit hooks (nếu bạn đang dùng Husky + lint-staged): Biome có cờ --staged native để chỉ xử lý file được staged, nên lint-staged không còn cần thiết:
# .husky/pre-commit
npx biome check --staged
Cờ --staged có từ Biome v1.7.0.
Repo lớn: bật VCS integration trong biome.json để Biome chỉ xử lý các file đã thay đổi:
{
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}
}
Nguồn: Biome CI docs via AppSignal migration guide.
Bước 8: Gỡ cài đặt ESLint và Prettier
Chỉ thực hiện bước này sau Bước 9 (kiểm tra parity). Khi đã hài lòng:
# ESLint core
npm uninstall eslint
# ESLint plugins — điều chỉnh theo deps thực tế của bạn
npm uninstall \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
eslint-plugin-react \
eslint-plugin-react-hooks \
eslint-plugin-jsx-a11y \
eslint-plugin-import \
eslint-plugin-unicorn \
eslint-config-prettier \
eslint-config-airbnb \
eslint-config-airbnb-base
# Prettier
npm uninstall prettier prettier-plugin-tailwindcss
# Xóa file config
rm -f .eslintrc.json .eslintrc.js .eslintignore
rm -f .prettierrc .prettierrc.json .prettierignore
Kiểm tra lại package.json để tìm các tham chiếu eslint hoặc prettier còn sót trong devDependencies — một số transitive dep có thể đã được hoisted.
Bước 9: Kiểm tra parity
Chạy Biome trên toàn bộ codebase:
npx @biomejs/biome check --write .
Cờ --write áp dụng safe auto-fixes. Commit những thay đổi đó thành một commit riêng “biome: auto-fix” để diff dễ đọc.
Sau đó chạy không có --write để xem còn gì chưa xử lý:
npx @biomejs/biome check .
Các vi phạm còn lại là thứ bạn cần fix thủ công, hoặc là rule bạn nên tắt trong biome.json vì project cố tình không tuân theo. Đi qua từng cái. Khi biome check . exit sạch, bạn đã xong.
Với các rule cần bulk unsafe fixing (như chuyển toàn bộ var sang const):
npx @biomejs/biome check --write --unsafe .
Xem lại diff cẩn thận trước khi commit — unsafe fixes thay đổi semantics.
Khi nào không nên migrate
Đừng migrate nếu bất kỳ điều nào sau đây áp dụng cho project của bạn:
eslint-plugin-security là bắt buộc. Không có tương đương trong Biome tính đến v2.4.15. Team security phụ thuộc vào các rule này cần ở lại với ESLint.
@typescript-eslint/no-floating-promises hoặc no-misused-promises là không thể bỏ qua. Biome v2.0 đã thêm type-aware linting với coverage một phần cho các trường hợp floating-promise, nhưng parity đầy đủ vẫn chưa đạt được. Nếu codebase async-heavy của bạn cần 100% coverage cho unhandled promise, gap này thực sự quan trọng.
Custom ESLint rules trong production. Biome v2.0 ra mắt hệ thống plugin dựa trên GritQL, nhưng đây là phiên bản đầu tiên. Đừng giả định các rule tùy chỉnh sẽ chuyển dễ dàng mà không cần test. Nếu chúng phức tạp, chi phí chuyển đổi có thể cao hơn lợi ích về tốc độ.
Vue/Svelte/Astro với linting framework-specific nặng. Biome v2.4 đã cải thiện việc parse framework nhưng vẫn còn gap theo phản hồi cộng đồng. eslint-plugin-next được hỗ trợ một phần; eslint-plugin-vue, eslint-plugin-svelte, và eslint-plugin-astro vẫn còn thiếu sót. Test trên codebase thực của bạn trước khi quyết định.
Config ESLint được phân phối dưới dạng npm package chung. Nếu bạn duy trì một org-wide ESLint config package mà hàng chục project khác dùng, phạm vi migrate sẽ mở rộng đáng kể. Lợi ích về tốc độ có thể không xứng với chi phí phối hợp.
SCSS linting. Biome không lint SCSS. Tính năng này có trong roadmap 2026 nhưng chưa có. Nếu bạn dùng stylelint cho CSS/SCSS và ESLint cho JS, phần ESLint vẫn có thể migrate; phần stylelint không liên quan.
Nếu bạn đang nâng cấp toàn bộ toolchain cùng lúc, Cách migrate từ Jest sang Vitest và Cách migrate từ Webpack sang Vite bao gồm phần test runner và bundler trong cùng lộ trình hiện đại hóa.
Tham khảo
- Hướng dẫn migrate chính thức của Biome
- Biome linter rules sources (ESLint mapping)
- Biome reference configuration
- Biome v2.0 release notes (type-aware linting)
- Biome roadmap 2026
- BetterStack: Biome vs ESLint benchmarks
- FireUp.pro: pre-commit hooks nhanh hơn 15×
- Kitty Giraudel: từ ESLint và Prettier sang Biome
- AppSignal: migrate JS project sang BiomeJS