Skip to content

Leave ESLint 8: run oxlint first and keep a slim flat-config ESLint for what it lacks #513

Description

@Pixnop

Summary

ESLint 8 has been end of life since 2024-10-05 and the repository still uses the legacy .eslintrc.cjs, so a migration is due whatever we choose. Measured on dev, oxlint covers most of what we lint for at about a twentieth of the time, but not everything. Proposal: oxlint runs first, a slimmed ESLint 9 (flat config) keeps the rules oxlint does not enforce for us, wired with eslint-plugin-oxlint so nothing is checked twice.

Measurements (dev, Node 22, median of three runs)

Time Findings
npm run lint:ci (ESLint 8.57) 10.2 s 0 errors, 14 warnings, all react-hooks/exhaustive-deps
oxlint 1.83.0 with the react plugin 0.53 s the same violations in the same 13 files (reported as 15, one split in two)

Parity

  • react-hooks/exhaustive-deps: implemented, on by default. rules-of-hooks: implemented, off by default (category "suspicious"), to switch on.
  • The typescript-eslint rules our config sets to error (no-explicit-any, ban-ts-comment, explicit-function-return-type, no-empty-function, no-empty-interface) and the no-restricted-imports guard that keeps src/domain pure all exist in oxlint but are off by default: each has to be enabled explicitly and proven with a failing fixture.
  • Type-aware linting needs the separate oxlint-tsgolint package, still experimental: not adopted here.
  • @oxlint/migrate only ported two rules and ignored every extends and both overrides blocks, so the config is written by hand.

What oxlint found that ESLint did not

  • Real: no-unsafe-optional-chaining in four test files (genuine), react/set-state-in-effect in 23 places and react/refs in 14, to triage rather than fix blindly.
  • Style: four unicorn hits.
  • Noise: two false positives on src/global.d.ts that tsc accepts.

Plan

  1. .oxlintrc.json written by hand: the rules above switched on, the two global.d.ts false positives ignored with a comment, a fixture test proving the domain import guard and rules-of-hooks fire.
  2. ESLint moved to 9 with a flat config reduced to what oxlint does not cover, plus eslint-plugin-oxlint.
  3. lint and lint:ci run oxlint then ESLint; CI unchanged otherwise. Prettier is separate and unaffected.
  4. The new real findings triaged in their own issue, not mixed into the migration.

Acceptance

  • The 14 known warnings are still reported, no rule we rely on is lost (one fixture per guard).
  • lint:ci wall time reported before and after.
  • No ESLint 8 package left in package.json.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ciWorkflows, Sonar, gatestech debtInherited debt, tracked to be paid down

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions