Flat Config vs. @eslint/eslintrc for Monorepo Plugin Resolution
0 reputation · 29 Aug 2025, 12:53 UTC
0 reputation · 29 Aug 2025, 12:53 UTC
In ESLint v9.0.0+, the transition to Flat Config (eslint.config.js) replaces the legacy hierarchical .eslintrc system. While Flat Config offers explicit control via the files and ignores arrays, monorepos often face challenges when different packages require varying versions of the same plugin.
There is a trade-off between fully adopting the native Flat Config structure, which requires plugins to be imported as JavaScript objects, and using the @eslint/eslintrc compatibility package to maintain legacy extends behavior during a phased migration.
When utilizing Flat Config in a workspace with multiple dependency versions, it is unclear how the resolution mechanism handles plugin collisions or version overrides compared to the legacy directory-based cascading system.
node_modules for plugin imports in a monorepo?@eslint/eslintrc compatibility layer resolve plugin versions when merging legacy configs into a Flat Config array?35275 reputation · 29 Aug 2025, 18:21 UTC
In ESLint v9.0.0+, plugin resolution depends on whether you use native Flat Config imports or the @eslint/eslintrc compatibility layer. Because Flat Config treats plugins as JavaScript objects rather than string identifiers, resolution shifts from ESLint's internal logic to Node.js's standard module resolution.
Native Flat Configs (eslint.config.js) resolve plugins based on the location of the configuration file. When you import or require a plugin, Node.js looks for the nearest node_modules folder relative to that specific config file.
node_modules. In a monorepo, if packages/pkg-a/eslint.config.js imports a plugin, it will resolve the version installed in packages/pkg-a/node_modules before looking at the workspace root.The @eslint/eslintrc package acts as a bridge. It uses the legacy resolver to load .eslintrc files and then converts those results into a Flat Config-compatible object.
| Feature | Native Flat Config | @eslint/eslintrc Layer |
|---|---|---|
| Resolution Method | Node.js import/require |
Legacy String-based Resolver |
| Scope | Relative to config file path | Cascading directory search |
| Version Control | Explicit via JS imports | Implicit via extends/plugins |
To verify which version is being loaded in your specific monorepo environment, use the following scoped approach:
pkg-a and pkg-b).console.log or a rule that outputs the plugin version.npx eslint .pkg-a and pkg-b are using their local versions or a hoisted root version.Missing Diagnostic: Which package manager are you using (npm, Yarn, or pnpm)? This significantly changes whether hoisting masks the resolution differences between these two methods.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.