Oxlint vs ESLint: qual linter de JS para CI?
O Oxlint (do projeto Oxc) é um linter baseado em Rust que roda ordens de magnitude mais rápido que o ESLint, que mantém o ecossistema completo de regras e plugins.
O ESLint é o linter padrão de JavaScript/TypeScript com o maior conjunto de regras e plugins. O Oxlint é um linter baseado em Rust focado em velocidade, cobrindo muitas regras comuns com configuração quase nula e melhorando a cobertura com o tempo.
Oxlint vs ESLint at a glance
| Oxlint | ESLint | |
|---|---|---|
| Implementação | Rust | JavaScript |
| Velocidade | Extremamente rápida | Mais lenta |
| Cobertura de regras | Muitas regras comuns, em crescimento | Completa, a maior |
| Ecossistema de plugins | Limitado, em crescimento | O maior |
| Config | Quase zero | Flexível |
| Lint com reconhecimento de tipos | Sim, via tsgo (TypeScript 7) | Sim, via typescript-eslint |
| Formato de configuração | Configuração própria, no estilo ESLint | Flat config (eslint.config.js) na v9 e v10 |
| Autofix | Sim (--fix) | Sim (--fix) |
| Integração com editor | Disponível | Universal |
| Substituto drop-in | Ainda não | n/a |
No CI
O Oxlint pode fazer lint de bases de código enormes em uma fração do tempo do ESLint, o que o torna atraente como um gate rápido de primeira passagem. Ele ainda não cobre todas as regras ou plugins do ESLint, então muitas equipes rodam o Oxlint para velocidade e mantêm o ESLint para as regras que faltam ao Oxlint - frequentemente o Oxlint a cada push e uma passagem mais completa do ESLint com menos frequência. Se você depende de plugins custom ou específicos de framework, o ESLint continua essencial.
| ESLint lint step | Oxlint at 50x | Oxlint at 100x |
|---|---|---|
| 10 seconds | 0.2 s | 0.1 s |
| 60 seconds | 1.2 s | 0.6 s |
| 3 minutes | 3.6 s | 1.8 s |
| 8 minutes (large monorepo) | 9.6 s | 4.8 s |
Use-os juntos
Rode o Oxlint como um pré-check rápido e o ESLint para as regras que ele não cobre; não precisa cachear nada especial, já que o linting é limitado por CPU. Ambos rodam em managed runners; runners gerenciados mais rápidos encurtam a passagem do ESLint em repos grandes.
- What ports cleanly: core correctness rules, TypeScript rules, React hooks and JSX rules, and the common test-framework plugins.
- What does not: your own in-house rules, and smaller community plugins nobody has ported.
- Rule *names* mostly match ESLint, so disable comments and config intent carry over more easily than a rewrite would suggest.
O lint com reconhecimento de tipos é a mudança mais nova e maior
Regras com reconhecimento de tipos são as que precisam do type checker e não apenas da árvore sintática: promises soltas, propagação insegura de any, promises mal usadas. Historicamente eram exclusivas do ESLint via typescript-eslint, e também eram as regras mais lentas de qualquer configuração porque exigem uma verificação de tipos completa.
- O oxlint agora suporta lint com reconhecimento de tipos integrando-se ao port em Go do TypeScript (tsgo, TypeScript 7), habilitando verificações como detecção de promises soltas.
- Isso remove o que era a razão técnica mais forte para uma base TypeScript não poder sequer considerar o oxlint.
- É também a área que se move mais rápido, então verifique a cobertura atual contra as regras das quais você realmente depende em vez de presumir paridade.
O bloqueio real: plugins customizados estão em alfa
Se você mantém regras internas, é isso que decide tudo. O oxlint suporta plugins JS compatíveis com o ecossistema de plugins do ESLint, mas esse suporte está documentado como alfa. Alfa serve para um experimento de lint e não serve para o portão que bloqueia os seus merges.
- Um repositório sem regras customizadas e com plugins mainstream muitas vezes já pode migrar hoje.
- Um repositório com regras internas que codificam restrições arquiteturais deve manter o ESLint especificamente para essas regras.
- Plugins nativos (Rust) são estáveis, mas significam escrever Rust, o que é uma proposta diferente de manter uma regra em JS.
O padrão que repositórios grandes de fato usam: os dois
Em vez de escolher, rode o oxlint como um pré-filtro rápido e o ESLint para as regras que o oxlint ainda não cobre. Você ganha o ciclo rápido de feedback onde importa e mantém a cobertura completa onde precisa.
# package.json scripts
{
"scripts": {
"lint:fast": "oxlint",
"lint:full": "eslint .",
"lint": "oxlint && eslint ."
}
}
# .github/workflows/ci.yml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
# Fails in about a second on the 865 rules oxlint covers,
# so the slow full pass only runs on code that already passes.
- run: npx oxlint
- run: npx eslint .Quando uma migração completa faz sentido
- Faça o inventário dos seus plugins do ESLint e regras customizadas, e confira cada um contra a lista de regras do oxlint.
- Se nada customizado aparecer, rode
oxlintao lado do ESLint no CI por algumas semanas e compare os achados. - Investigue cada discordância. Regras com o mesmo nome podem divergir nas bordas, e é nessas bordas que uma mudança silenciosa de comportamento se esconde.
- Mova a passagem rápida para um hook de pre-commit quando confiar nela, para que falhas de lint parem de chegar ao CI.
- Aposente o ESLint apenas quando o diff estiver vazio e nada na sua configuração depender do suporte alfa a plugins JS.
The switching cost is mostly in the parts nobody lists
- Assertions and mocks usually port mechanically when the target implements a compatible API; custom transformers and framework plugins do not.
- Snapshot formats differ between runners, so plan to regenerate and review rather than port.
- Run both suites in parallel in CI for a period and diff the results. A migration that changes which tests fail is not a migration, it is a regression you have not found yet.
- Coverage numbers move on a runner change even when the tests do not, because instrumentation differs. Re-baseline any coverage gate deliberately.
The verdict
Quer uma passagem de lint ultrarrápida e suas regras críticas estão cobertas: Oxlint (frequentemente ao lado do ESLint). Precisa do ecossistema completo de regras e plugins: ESLint. Muitas equipes os combinam - Oxlint para velocidade, ESLint para cobertura.
Perguntas frequentes
O oxlint é um substituto drop-in do ESLint?
Quanto o oxlint é mais rápido que o ESLint?
O oxlint suporta lint com reconhecimento de tipos?
Quantas regras o oxlint tem?
Posso rodar oxlint e ESLint juntos?
oxlint primeiro para que a maioria das violações apareça em cerca de um segundo, e depois eslint . para as regras que o oxlint não cobre. A latência de falha melhora sem perda de cobertura.Quem usa oxlint em produção?
O oxlint suporta autofix?
oxlint --fix, no mesmo formato de eslint --fix. Por ser muito mais rápido, o autofix ao salvar é prático de um jeito que uma passagem lenta do ESLint frequentemente não é.