-
chore(repo): migrate nx repo to eslint v9 flat config (#35359)
发布于
2026-04-22 12:34:44 +00:00 Current Behavior
The nx repo uses the legacy eslintrc format (
.eslintrc.json,
.eslintignore) with ESLint v8 and outdated plugin versions. Several of
those plugins ship code that crashes under ESLint v9 (context.getScope
removed, etc.), and the@nx/eslint/@nx/eslint-pluginsources still
reference APIs removed in v9 (Linter.defineParser,
Linter.defineRule, classicLinter.Configshape).Expected Behavior
Every project in the repo uses an
eslint.config.mjsflat config, the
ESLint ecosystem is on the latest v9-compatible versions, and
@nx/eslint/@nx/eslint-pluginsources compile and test cleanly
against the v9 type split.Main changes
- Replaced every
.eslintrc.json/.eslintignorewith an
eslint.config.mjs. - Rewrote the root
eslint.config.mjs: - Exports a named
baseConfigthat leaf configs import, plus a default
export that opts out of linting (**/*ignored) so the root acts as a
shared base and isn't lint-checked directly.- Drops
FlatCompatin favor of native plugin imports.
- Drops
- Exports shared
reactHooksV7Off,e2eTestOnlyIgnores, and a
storybookConfigswrapper that filters v10's preset down to
storybook/*rules (the preset references foreign rules like
import-x/*that we don't register). - Cleaned up leaf configs emitted by the generator: deduplicated file
entries, merged splitpackage.jsonblocks, fixed the jsonc parser
namespace import after v3 dropped its default export. - Scoped the 15 e2e projects to
*.test.tsfiles only via a shared
export. - Bumped the ESLint ecosystem to the latest v9-compatible versions:
eslint@^9.39.4,@eslint/js@^9.39.4,@typescript-eslint/*@^8.58.2,
eslint-plugin-storybook@^10.3.5,eslint-plugin-react-hooks@^7.1.0,
eslint-plugin-jsx-a11y@^6.10.2,eslint-plugin-import@^2.32.0,
eslint-plugin-playwright@^2.10.1,eslint-plugin-cypress@^6.3.1,
eslint-plugin-jest@^29.15.2,toml-eslint-parser@^1.0.3,
jsonc-eslint-parser@^3.1.0,angular-eslint@^21.3.1. Dropped
@eslint/eslintrc,@types/eslint,@types/eslint__js. - Aligned
@nx/eslintsource with the v9 type split:Linter.Config→
Linter.LegacyConfig,ESLint.Options→ESLint.LegacyOptions
wherever the underlying shape is eslintrc. - Rewrote
@nx/eslint-pluginrule specs (dependency-checks,
enforce-module-boundaries) as flat-config inline tests since
Linter.defineParser/defineRulewere removed in v9. - Aligned react/angular/expo/react-native add-linting helpers with the
v9 type split. - Migrated
tools/eslint-rulesspecs fromTSESLint.RuleTester(legacy
config, rejected by v9's flat Linter) to
@typescript-eslint/rule-tester; addedisolatedModules: trueso
ts-jest resolves the new types undermodule: node16. - Downgraded the new react-hooks v7 rules to
offvia a shared export
so the migration doesn't require rewriting legacy code. - Auto-fixed unused eslint-disable directives
(linterOptions.reportUnusedDisableDirectivesdefaults to warn in v9). - Ignored
packages/workspace/**/__fixtures__/**in lint and updated
the affected snapshot so the fixture matches what the jest generator
templates actually emit.
Note on ESLint v10
This PR stays on ESLint v9. A few plugins we rely on
(eslint-plugin-import,eslint-plugin-jsx-a11y,
eslint-plugin-react) still don't declare v10 peer support. The jump to
v10 will happen in a follow-up PR once those plugins publish
v10-compatible releases.下载附件
- Replaced every