Biome — Toolchain TypeScript Thay ESLint + Prettier
Biome là toolchain Rust cho JS/TS, thay thế ESLint + Prettier. Tốc độ nhanh hơn 10-20x, zero config, tích hợp sẵn linter + formatter.
Biome là unified toolchain cho JavaScript/TypeScript/JSX/TSX — vừa linter, vừa formatter, viết bằng Rust.
ESLint (lint) + Prettier (format)
↓ ↓
Biome (cả hai — nhanh hơn 10-20x)plaintextKhông plugin, không config rườm rà, không chờ đợi.
Tại Sao Biome?#
Vấn đề với ESLint + Prettier#
# Setup mệt:
npm i -D eslint prettier eslint-config-prettier \
@typescript-eslint/parser @typescript-eslint/eslint-plugin \
eslint-plugin-react eslint-plugin-react-hooks
# 5 file config:
.eslintrc.js .prettierrc .eslintignore .prettierignore tsconfig.jsonbashESLint 8s — chậm. Mỗi lần chạy linter: load parser, load plugin, parse AST, traverse, report. Prettier parse lại từ đầu.
Biome khác gì?#
# Chỉ 1 lệnh:
npm i -D @biomejs/biome
# 1 file cấu hình (tùy chọn):
biome.jsonbashBiome dùng chung một AST parser (rust-based), chạy lint + format trong một pass. Kết quả: nhanh hơn ~10-20x.
| ESLint + Prettier | Biome | |
|---|---|---|
| Thời gian format | 300-800ms | ~20-50ms |
| Thời gian lint + format | 2-5s | ~50-100ms |
| File config | 3-5 files | 0-1 file |
| Plugin | Hàng trăm | Built-in (mở rộng dần) |
| Language support | JS/TS + plugin | JS/TS/JSX/TSX/JSON/CSS |
Cài Đặt#
mkdir biome-demo && cd biome-demo
npm init -y
npm i -D @biomejs/biome
npx biome init # tạo biome.jsonbashbiome.json mặc định:
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 80
}
}jsonChạy thử:
npx biome format src/ # format
npx biome lint src/ # lint
npx biome check src/ # lint + format + organize import
npx biome check --apply src/ # tự động sửabashFormatter#
Biome format giống Prettier nhưng nhanh hơn và có khác biệt nhỏ:
// Input
const foo = { a: 'hello', b: 'world', c: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }
const bar: Record<string, string> = { 'some-key': 'some-value', 'another-key': 'another-value' }
// Prettier output
const foo = {
a: 'hello',
b: 'world',
c: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
};
const bar: Record<string, string> = {
'some-key': 'some-value',
'another-key': 'another-value',
};
// Biome output (gần giống, khác dấu phẩy cuối và indent default)
const foo = {
a: "hello",
b: "world",
c: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
};typescriptKhác biệt chính với Prettier:
- Format attribute kiểu khác
- Import sorting (built-in, không cần plugin)
- Semicolons mặc định: có
- Quote style mặc định: double
Import Organization#
// Input lộn xộn
import { z } from 'zod';
import { readFile } from 'node:fs';
import { useEffect } from 'react';
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
// Sau biome check --apply
import { readFile } from 'node:fs';
import { useEffect } from 'react';
import { z } from 'zod';
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
// ↑ node built-in → npm packages → local (tự động)typescriptKhông cần eslint-plugin-simple-import-sort hay @trivago/prettier-plugin-sort-imports.
Linter#
Biome linter có sẵn ~200+ rules, được nhóm theo category:
{
"linter": {
"rules": {
"recommended": true,
"complexity": {
"noForEach": "error",
"noBannedTypes": "error"
},
"style": {
"noNonNullAssertion": "error",
"useConst": "error",
"useTemplate": "error"
},
"suspicious": {
"noConsoleLog": "warn"
},
"correctness": {
"noUnusedVariables": "error"
}
}
}
}jsonRule categories: a11y, complexity, correctness, performance, security, style, suspicious.
Rule Ví Dụ#
// complexity/noForEach
// ❌ Biome báo lỗi: forEach không hỗ trợ async, prefer for...of
[1, 2, 3].forEach(async (n) => {
await fetch(`/api/${n}`);
});
// ✅
for (const n of [1, 2, 3]) {
await fetch(`/api/${n}`);
}typescript// correctness/noUnusedVariables
function process(data: string) {
const result = transform(data); // ❌ result không dùng
return true;
}typescript// style/useTemplate
const name = 'World';
const msg = 'Hello, ' + name + '!'; // ❌ prefer template literal
const msg2 = `Hello, ${name}!`; // ✅typescriptMigration từ ESLint + Prettier#
Bước 1: Cài Biome#
npm i -D @biomejs/biome
npx biome initbashBước 2: Xoá ESLint + Prettier#
npm uninstall eslint prettier eslint-config-prettier \
@typescript-eslint/parser @typescript-eslint/eslint-plugin \
eslint-plugin-react eslint-plugin-react-hooks
rm .eslintrc.js .eslintrc.json .prettierrc .eslintignore .prettierignorebashBước 3: Chạy check và sửa#
npx biome check --apply src/bashBước 4: Thêm vào package.json#
{
"scripts": {
"lint": "biome check src/",
"format": "biome format --write src/",
"check": "biome ci src/"
}
}jsonEditor Integration#
VS Code#
npx @biomejs/biome init --vscode
# Hoặc cài extension "Biome" từ marketplacebash.vscode/settings.json:
{
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit"
}
}jsonLưu ý khi đã có ESLint extension#
Tắt ESLint extension hoặc disable cho project:
{
"eslint.enable": false
}jsonCI/CD#
# GitHub Actions
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx biome ci src/
# biome ci — không sửa file, chỉ báo lỗiyaml# Husky + lint-staged
# .lintstagedrc.json
{
"*.{js,ts,jsx,tsx,json}": ["biome check --apply"]
}yamlIgnore Files#
{
"files": {
"ignore": ["dist", "build", ".next", "coverage"]
}
}jsonHoặc file .gitignore — Biome tự đọc .gitignore mặc định.
Tùy Chỉnh Format#
{
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf",
"attributePosition": "auto"
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true
}
},
"json": {
"formatter": {
"trailingCommas": "none"
}
}
}jsonKhi Nào Nên Dùng Biome?#
✅ Nên#
- Dự án mới bằng TypeScript
- Team đang dùng ESLint + Prettier, muốn chạy nhanh hơn
- Monorepo với nhiều package
- CI pipeline chậm vì lint
- Developer experience — muốn ít config hơn
❌ Chưa nên#
- Cần plugin ESLint đặc thù (
eslint-plugin-import,eslint-plugin-jsx-a11ynâng cao) - Dùng
eslint-plugin-vue/eslint-plugin-angular— Biome chưa hỗ trợ - Dùng Prettier plugin cho Markdown/YAML — Biome format JSON/JS/TS/CSS
- Custom parser / custom ESLint rule nội bộ
So Sánh Tốc Độ#
Codebase ~1000 file TypeScript:
# ESLint + Prettier
time npx eslint src/ --fix && npx prettier --write src/
# → ~8.4s
# Biome
time npx biome check --apply src/
# → ~0.4s
# Nhanh hơn ~20xbashKhông chỉ nhanh hơn — còn ít flaky hơn vì không có conflict giữa plugin.
Biome trong Monorepo#
{
"workspace": ["packages/*"]
}json# Cấu trúc
biome.json # root config
packages/
web/biome.json # override
api/biome.jsonbash// packages/web/biome.json — override một phần
{
"extends": ["../../biome.json"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off"
}
}
}
}jsonTổng Kết#
Biome mang lại trải nghiệm dev tooling đơn giản hơn, nhanh hơn, ít config hơn.
| ESLint + Prettier | Biome | |
|---|---|---|
| Cài đặt | 5+ dependencies | 1 dependency |
| Config | 3-5 files | 0-1 file |
| Tốc độ | 1-10s | 50-500ms |
| Language | JS/TS (plugin) | JS/TS/JSX/TSX/JSON/CSS |
| Import sort | Plugin riêng | Built-in |
| Parser | 2 parsers (lint + format) | 1 parser chung |
| Rust | ❌ | ✅ |
# Chỉ cần nhớ 3 lệnh
npx biome format src/ # format
npx biome lint src/ # lint
npx biome check --apply src/ # lint + format + organize importbashBiome chưa hoàn thiện như ESLint 15 năm tuổi, nhưng cho 90% use case hàng ngày, nó nhanh hơn, đơn giản hơn, và đỡ đau đầu hơn hẳn.