Pular para o conteúdo
LatchkeyLatchkey home

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

OxlintESLint
ImplementaçãoRustJavaScript
VelocidadeExtremamente rápidaMais lenta
Cobertura de regrasMuitas regras comuns, em crescimentoCompleta, a maior
Ecossistema de pluginsLimitado, em crescimentoO maior
ConfigQuase zeroFlexível
Lint com reconhecimento de tiposSim, via tsgo (TypeScript 7)Sim, via typescript-eslint
Formato de configuraçãoConfiguração própria, no estilo ESLintFlat config (eslint.config.js) na v9 e v10
AutofixSim (--fix)Sim (--fix)
Integração com editorDisponívelUniversal
Substituto drop-inAinda nãon/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 stepOxlint at 50xOxlint at 100x
10 seconds0.2 s0.1 s
60 seconds1.2 s0.6 s
3 minutes3.6 s1.8 s
8 minutes (large monorepo)9.6 s4.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.

Running both, fast pass first
# 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

  1. Faça o inventário dos seus plugins do ESLint e regras customizadas, e confira cada um contra a lista de regras do oxlint.
  2. Se nada customizado aparecer, rode oxlint ao lado do ESLint no CI por algumas semanas e compare os achados.
  3. 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.
  4. Mova a passagem rápida para um hook de pre-commit quando confiar nela, para que falhas de lint parem de chegar ao CI.
  5. 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?
Ainda não. Ele cobre mais de 865 regras e os nomes das regras coincidem em grande parte com os do ESLint, então configurações mainstream portam bem. O bloqueio é que o suporte a plugins JS, do qual dependem regras customizadas e de nicho, ainda é alfa. Repositórios sem regras internas costumam poder migrar; os que têm devem manter o ESLint para essas regras.
Quanto o oxlint é mais rápido que o ESLint?
O benchmark publicado é de 50 a 100 vezes mais rápido. Na prática isso transforma um passo de lint de 60 segundos em cerca de um segundo, e um lint de monorepo de oito minutos em menos de dez segundos. O efeito maior é qualitativo: um lint de menos de um segundo pode rodar a cada save e como hook de pre-commit, então falhas param de chegar ao CI.
O oxlint suporta lint com reconhecimento de tipos?
Sim, pela integração com o port em Go do TypeScript (tsgo, TypeScript 7), que habilita verificações como detecção de promises soltas. Isso é recente e avança rápido, então verifique a cobertura das regras específicas de que você depende em vez de presumir paridade total com o typescript-eslint.
Quantas regras o oxlint tem?
Mais de 865, abrangendo regras core do ESLint, regras de TypeScript e conjuntos de regras de plugins populares, incluindo React, Jest e Vitest.
Posso rodar oxlint e ESLint juntos?
Sim, e é o padrão recomendado. Rode 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?
Elastic Kibana, Sentry e Cloudflare são adotantes citados. Note que são bases de código grandes, o caso em que a diferença de velocidade mais se acumula e em que uma passagem completa do ESLint é mais dolorosa.
O oxlint suporta autofix?
Sim, via 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 é.
Meus comentários de disable do ESLint continuam funcionando?
Em grande parte, porque o oxlint deliberadamente espelha os nomes de regras do ESLint. Dito isso, regras com o mesmo nome podem divergir nas bordas, então rode os dois em paralelo por um período e compare os achados antes de aposentar qualquer coisa.

Guias relacionados