O Biome é um toolchain JavaScript/TypeScript ultra-rápido feito em Rust. Integra as funcionalidades do ESLint e Prettier em uma única ferramenta, melhorando a experiência de desenvolvimento com velocidade avassaladora. Em 2025, com o lançamento do Biome 2.0, a adoção em mais projetos está avançando.
O que é o Biome
Comparação de Toolchains
flowchart TB
subgraph Traditional["Configuração Tradicional"]
Workflow1["Fluxo de Desenvolvimento"]
ESLint["ESLint<br/>(JavaScript)"]
Prettier["Prettier<br/>(JavaScript)"]
TSC["TypeScript<br/>tsc"]
Config1["Múltiplos arquivos de configuração necessários<br/>(.eslintrc, .prettierrc, tsconfig.json)"]
Workflow1 --> ESLint
Workflow1 --> Prettier
Workflow1 --> TSC
ESLint --> Config1
Prettier --> Config1
TSC --> Config1
end
flowchart TB
subgraph BiomeArch["Configuração com Biome"]
Workflow2["Fluxo de Desenvolvimento"]
Biome["Biome (Rust)<br/>✓ Linter<br/>✓ Formatter<br/>✓ Import Sort"]
Config2["Gerenciado com 1 arquivo biome.json"]
Workflow2 --> Biome --> Config2
end
Comparação de Desempenho
| Ferramenta | Processamento de 1000 arquivos | Uso de Memória |
|---|---|---|
| ESLint + Prettier | Cerca de 30 segundos | ~500MB |
| Biome | Cerca de 0,5 segundos | ~50MB |
Cerca de 60x mais rápido, 1/10 da memória
Instalação e Configuração
Instalação Básica
# npm
npm install --save-dev --save-exact @biomejs/biome
# pnpm
pnpm add --save-dev --save-exact @biomejs/biome
# yarn
yarn add --dev --exact @biomejs/biome
# bun
bun add --dev --exact @biomejs/biome
# Inicialização do arquivo de configuração
npx @biomejs/biome init
Arquivo de Configuração Básico
// biome.json
{
"$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": 100
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "all",
"semicolons": "always"
}
}
}
Configuração de Scripts no package.json
{
"scripts": {
"lint": "biome lint .",
"lint:fix": "biome lint --write .",
"format": "biome format --write .",
"check": "biome check .",
"check:fix": "biome check --write .",
"ci": "biome ci ."
}
}
Configuração Detalhada
Exemplo de Configuração Completa
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"files": {
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx"],
"ignore": [
"node_modules",
"dist",
"build",
".next",
"coverage",
"*.min.js"
]
},
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noExcessiveCognitiveComplexity": {
"level": "warn",
"options": {
"maxAllowedComplexity": 15
}
},
"noForEach": "warn"
},
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error",
"useExhaustiveDependencies": "warn"
},
"performance": {
"noAccumulatingSpread": "warn",
"noDelete": "warn"
},
"security": {
"noDangerouslySetInnerHtml": "error"
},
"style": {
"noNonNullAssertion": "warn",
"useConst": "error",
"useTemplate": "error",
"noParameterAssign": "error"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn",
"noDebugger": "error"
},
"nursery": {
"useSortedClasses": {
"level": "warn",
"options": {
"attributes": ["className", "class"],
"functions": ["clsx", "cn", "cva"]
}
}
}
}
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 100,
"attributePosition": "auto"
},
"javascript": {
"formatter": {
"enabled": true,
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false
},
"parser": {
"unsafeParameterDecoratorsEnabled": true
}
},
"json": {
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
}
},
"css": {
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"quoteStyle": "double"
},
"linter": {
"enabled": true
}
},
"overrides": [
{
"include": ["*.test.ts", "*.test.tsx", "*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off"
}
}
}
},
{
"include": ["*.config.js", "*.config.ts"],
"linter": {
"rules": {
"style": {
"noDefaultExport": "off"
}
}
}
}
]
}
Categorias de Regras do Linter
Lista de Categorias de Regras
| Categoria | Exemplo de Regra | Descrição |
|---|---|---|
| a11y (Acessibilidade) | useAltText | Exige atributo alt em imagens |
| useKeyWithClickEvents | Operação por teclado em eventos de clique | |
| complexity (Complexidade) | noBannedTypes | Detecta uso de tipos proibidos |
| noForEach | Recomenda for…of em vez de forEach | |
| noExcessiveCognitiveComplexity | Limite de complexidade cognitiva | |
| correctness (Correção) | noUnusedVariables | Detecta variáveis não utilizadas |
| noUnusedImports | Detecta imports não utilizados | |
| useExhaustiveDependencies | Array de dependências do useEffect | |
| performance (Desempenho) | noAccumulatingSpread | Proíbe acumulação de operadores spread |
| noDelete | Alerta sobre uso do operador delete | |
| security (Segurança) | noDangerouslySetInnerHtml | Detecta vulnerabilidades XSS |
| noGlobalEval | Proíbe uso de eval() | |
| style (Estilo) | useConst | Usar const para variáveis não reatribuídas |
| useTemplate | Template literals em vez de concatenação | |
| noParameterAssign | Proíbe reatribuição de parâmetros | |
| suspicious (Código Suspeito) | noExplicitAny | Alerta sobre uso do tipo any |
| noConsoleLog | Alerta sobre uso de console.log | |
| noDebugger | Proíbe declarações debugger |
Exemplo de Configuração Detalhada de Regras
{
"linter": {
"rules": {
"correctness": {
"useExhaustiveDependencies": {
"level": "warn",
"options": {
"hooks": [
{
"name": "useQuery",
"stableResult": [1]
},
{
"name": "useMutation",
"stableResult": [1]
},
{
"name": "useCustomHook",
"closureIndex": 0,
"dependenciesIndex": 1
}
]
}
}
}
}
}
}
Migração do ESLint/Prettier
Checklist de Migração
# 1. Instalar o Biome
npm install --save-dev @biomejs/biome
# 2. Inicializar arquivo de configuração
npx @biomejs/biome init
# 3. Migrar configuração do ESLint (automático)
npx @biomejs/biome migrate eslint --write
# 4. Migrar configuração do Prettier (automático)
npx @biomejs/biome migrate prettier --write
Tabela de Correspondência de Regras ESLint
| ESLint | Biome | Categoria |
|---|---|---|
no-unused-vars | noUnusedVariables | correctness |
no-console | noConsoleLog | suspicious |
eqeqeq | noDoubleEquals | suspicious |
prefer-const | useConst | style |
no-var | noVar | style |
@typescript-eslint/no-explicit-any | noExplicitAny | suspicious |
react-hooks/exhaustive-deps | useExhaustiveDependencies | correctness |
jsx-a11y/alt-text | useAltText | a11y |
Estratégia de Migração Gradual
// biome.json - Configuração para migração gradual
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
// Inicialmente apenas avisos
"correctness": {
"noUnusedVariables": "warn",
"noUnusedImports": "warn"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "off" // Desabilitado inicialmente
}
}
}
}
# Remover ESLint/Prettier após migração
npm uninstall eslint prettier eslint-config-prettier eslint-plugin-*
# Remover arquivos de configuração
rm .eslintrc* .prettierrc* .eslintignore .prettierignore
Integração com Editor
VS Code
// .vscode/extensions.json
{
"recommendations": ["biomejs.biome"]
}
// .vscode/settings.json
{
// Biome como formatador padrão
"editor.defaultFormatter": "biomejs.biome",
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
// Formatar automaticamente ao salvar
"editor.formatOnSave": true,
// Executar code actions ao salvar
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
},
// Desabilitar ESLint/Prettier
"eslint.enable": false,
"prettier.enable": false
}
Neovim (nvim-lspconfig)
-- init.lua
require('lspconfig').biome.setup({
cmd = { 'npx', 'biome', 'lsp-proxy' },
root_dir = require('lspconfig.util').root_pattern('biome.json', 'biome.jsonc'),
single_file_support = false,
})
-- Integração com null-ls.nvim
local null_ls = require('null-ls')
null_ls.setup({
sources = {
null_ls.builtins.formatting.biome,
null_ls.builtins.diagnostics.biome,
},
})
JetBrains IDE (WebStorm, etc.)
Passos de configuração:
1. Settings → Languages & Frameworks → JavaScript → Code Quality Tools → Biome
2. Marcar "Enable"
3. Biome package: node_modules/@biomejs/biome
4. Configuration file: biome.json
Configuração de formatação:
1. Settings → Editor → Code Style
2. Desmarcar "Enable EditorConfig support"
3. Settings → Tools → Actions on Save
4. Marcar "Reformat code" e "Run Biome"
Integração com CI/CD
GitHub Actions
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Biome CI
run: npx @biomejs/biome ci .
# Adicionar anotações inline no PR
lint-review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome with reviewdog
uses: reviewdog/action-biome@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
GitLab CI
# .gitlab-ci.yml
stages:
- lint
biome:
stage: lint
image: node:20-alpine
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
script:
- npm ci
- npx @biomejs/biome ci .
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
Hook pre-commit (Husky + lint-staged)
# Instalação do Husky
npm install --save-dev husky lint-staged
npx husky init
// package.json
{
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css}": [
"biome check --write --no-errors-on-unmatched"
]
}
}
# .husky/pre-commit
npx lint-staged
Uso Avançado
API de Plugins (Recurso Experimental)
// biome-plugin.js - Exemplo de regra personalizada
export default {
name: 'my-custom-rules',
rules: {
noTodoComments: {
meta: {
docs: {
description: 'Proíbe comentários TODO em código de produção',
},
},
create(context) {
return {
Comment(node) {
if (node.value.includes('TODO')) {
context.report({
node,
message: 'Comentários TODO devem ser resolvidos antes do merge',
});
}
},
};
},
},
},
};
Configuração para Monorepo
// biome.json na raiz
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"extends": [],
"files": {
"ignore": ["packages/*/dist", "packages/*/node_modules"]
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"formatter": {
"enabled": true
}
}
// packages/web/biome.json - Configuração específica do pacote
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"extends": ["../../biome.json"],
"linter": {
"rules": {
"correctness": {
"useExhaustiveDependencies": "warn"
}
}
}
}
Ordenação Personalizada de Imports
{
"javascript": {
"organizeImports": {
"groups": [
["react", "react-dom"],
["^@?\\w"],
["^@/"],
["^\\.\\."],
["^\\."]
]
}
}
}
Solução de Problemas
Problemas Comuns e Soluções
# Limpar cache
rm -rf node_modules/.cache/biome
# Saída detalhada de erros
npx @biomejs/biome check --verbose .
# Debug de arquivo específico
npx @biomejs/biome lint --verbose src/problematic-file.ts
# Validar configuração
npx @biomejs/biome check --config-path biome.json --verbose
Comentários para Suprimir Erros
// Desabilitar regra específica para o arquivo inteiro
// biome-ignore-all lint/suspicious/noExplicitAny: Legacy code
// Desabilitar apenas a próxima linha
// biome-ignore lint/suspicious/noExplicitAny: Necessário para esta API
const data: any = response.data;
// Desabilitar múltiplas regras
// biome-ignore lint/style/useConst lint/correctness/noUnusedVariables: Intencional
let unusedVar = 'test';
// Desabilitar formatação
// biome-ignore format: Manter esta formatação
const matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
];
Benchmark de Desempenho
Comparação em projeto de grande escala (10.000 arquivos):
| Ferramenta | Tempo de lint | Tempo de format | Uso de Memória |
|---|---|---|---|
| ESLint | 120s | - | 1,2GB |
| Prettier | - | 45s | 800MB |
| ESLint+Prettier | 165s | (total) | 2,0GB |
| Biome | 2s | 1,5s | 150MB |
| Taxa de Melhoria | 60x mais rápido | 30x mais rápido | 13x de redução |
Resumo
O Biome melhora significativamente o toolchain de desenvolvimento frontend.
Benefícios de Adotar o Biome
| Item | ESLint+Prettier | Biome |
|---|---|---|
| Velocidade | Lento | Ultra-rápido (60x+) |
| Arquivos de configuração | Múltiplos | 1 arquivo |
| Dependências | Muitas | 1 |
| Uso de memória | Alto | Baixo |
| Consistência de configuração | Possíveis conflitos | Integrado |
Casos Recomendados para Adoção
- Novos projetos
- Projetos que precisam acelerar o CI
- Equipes que buscam simplificar configurações
- Ambientes Monorepo
O Biome está se tornando o novo padrão no ecossistema JavaScript.