跪拜 Guibai
← All articles
ESLint · Frontend Engineering · Code Standards

ESLint 10 Killed .eslintrc — Here's the Flat Config You Need Now

By 烬羽 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Any project upgrading to ESLint 10 will break silently until `.eslintrc` is replaced with an `eslint.config.mjs` file. The migration is mechanical but unforgiving: forgetting `globals` floods the output with `no-undef` errors, and mixing `"type": "commonjs"` with `.mjs` configs causes module resolution failures.

Summary

The `.eslintrc` format and its cascade resolution are gone as of ESLint 10. The replacement, flat config, exports a plain JS array of configuration objects. Each object declares its own file scope, plugins, and rules; the array order is the override order, eliminating the implicit merging that made old configs unpredictable. Built-in recommended rules now ship as the `@eslint/js` package, and environment globals require the separate `globals` package — two dependencies that catch most migration attempts. A live demo shows that `js/recommended` catches real bugs like unused variables, while formatting rules stay silent until you violate them, and `--fix` only touches style rules, not logic errors.

Takeaways
ESLint 10 ignores `.eslintrc` files completely; only `eslint.config.(js|mjs|cjs)` is read.
Flat config exports an array of objects; array order is the override order, with no implicit cascade merging.
`extends: "eslint:recommended"` becomes an explicit `import` from `@eslint/js`, mounted as a plugin, then referenced as `js/recommended`.
`env` fields are replaced by the `globals` package; missing it causes `no-undef` errors for `process`, `console`, and `__dirname`.
`overrides` disappears — each config object declares its own `files` field to scope where it applies.
`--fix` only auto-corrects formatting rules like `quotes` and `semi`; semantic rules like `no-unused-vars` and `no-console` cannot be auto-fixed.
Using `eslint.config.mjs` forces ESM parsing regardless of `package.json`'s `"type"` field, avoiding CommonJS/ESM clashes.
Conclusions

The cascade system's real cost was not performance but unpredictability: developers could not tell which config file a final rule came from, making debugging a guessing game.

Flat config's design shifts ESLint from a 'convention over configuration' tool toward an explicit module graph, which raises the initial setup cost but eliminates an entire class of silent misconfiguration bugs.

The split of built-in rules into `@eslint/js` and globals into a separate `globals` package suggests the ESLint team is unbundling the core to make the dependency surface visible and auditable.

Many developers will discover their old configs never actually enforced the rules they thought they did, because cascade merging silently overrode them — flat config makes that visible immediately.

Concepts & terms
Flat config
ESLint's new configuration system (default in v9, mandatory in v10) where config is a JS array of self-contained objects. Each object declares its own file scope, plugins, and rules; array order determines priority, replacing the old cascade merging.
Cascade configuration
The old `.eslintrc` resolution method where ESLint walked up the directory tree, merged every config file it found, and recursively resolved `extends` chains. This produced a final merged config whose origin was often opaque.
globals package
A standalone npm package that provides predefined sets of global variables (Node, browser, jest, etc.) for ESLint flat config. Replaces the old `env` field; must be installed and imported explicitly.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗