Issue
I've been scratching my head non stop trying to setup an ESlint configuration in my monorepo. I'm using Yarn 3.2.4 as the package manager. Here is a GitHub repo containing an example project.. Here is the project structure :
/monorepo
├── /configs
│ ├── /eslint
│ │ ├── index.js
│ │ └── package.json
│ ├── /jest
│ │ ├── index.js
│ │ └── package.json
│ ├── /prettier
│ │ ├── index.js
│ │ └── package.json
│ └── /typescript
│ ├── tsconfig.json
│ └── package.json
├── /packages
│ └── /mypackage
│ ├── .eslintrc.js
│ └── package.json
└── package.json
With the following :
/monorepo/package.json
(Root package.json)
{
...,
"workspaces": [
"configs/*",
"packages/*"
],
"scripts": {
"lint": "yarn workspaces foreach -pt run lint"
}
}
/monorepo/configs/eslint/package.json
{
...,
"name": "@monorepo/eslint-config",
"main": "index.js",
"peerDependencies": {
"eslint": "^8.27.0",
...
* other eslint plugins / configs *
...
}
}
/monorepo/configs/eslint/index.js
is just my normal eslint config file, extending and using the eslint config packages listed above/monorepo/packages/mypackage/package.json
{
...,
"devDependencies": {
"@monorepo/eslint-config": "workspace:*",
"eslint": "^8.27.0",
...
* other eslint plugins / configs *
...
}
}
/monorepo/packages/mypackage/.eslintrc.js
module.exports = {
extends: ['@monorepo/eslint-config']
};
Now with this config, IT WORKS. However what I find really annoying is that I need to specify the eslint configs/plugins dependencies in EVERY package of my mono repo. If I try to place these dependencies in the devDependencies
of the eslint-config package, and remove them from the mypackage
package (leaving only eslint
as a dev dependency) I get the following error message :
Error: Failed to load plugin '@typescript-eslint' declared in '.eslintrc.js » @monorepo/eslint-config': Your application tried to access @typescript-eslint/eslint-plugin, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.
Required package: @typescript-eslint/eslint-plugin
Required by: /path/to/monorepo/packages/mypackage/
Require stack:
- /path/to/monorepo/packages/mypackage/__placeholder__.js
Referenced from: /path/to/monorepo/.yarn/__virtual__/@monkvision-eslint-config-virtual-abbbf308a5/1/configs/eslint/index.js
at Function.require$$0.Module._resolveFilename (/path/to/monorepo/.pnp.cjs:16089:13)
at Function.resolve (node:internal/modules/cjs/helpers:108:19)
at Object.resolve (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2325:46)
at ConfigArrayFactory._loadPlugin (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3392:33)
at ConfigArrayFactory._loadExtendedPluginConfig (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3212:29)
at ConfigArrayFactory._loadExtends (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3133:29)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next (<anonymous>)
at ConfigArrayFactory._normalizeObjectConfigData (/path/to/monorepo/.yarn/cache/@eslint-eslintrc-npm-1.3.3-9e3a462140-f03e9d6727.zip/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next (<anonymous>)
So my question is : Is there any way to only declare the ESlint plugin depenencies ONCE (in the config project) and not in every package of my monorepo ?
Sorry for the long post and thanks in advance.
Solution
Okay so after a few days of reading about this subject, I think I've got a pretty good overview of this subject.
This is actually an issue related to ESlint, and it has nothing to do with yarn workspaces. It is actually a limitation of ESlint that forces shared configs to use peer dependencies. However there are some workarounds / future solutions. For people interested, I will copy / paste the message that I wrote for my team here at work :
Due to the limitations of how ESlint works right now, shared ESlint configurations need to specify their dependencies (such as other configs, plugins etc...) as peer dependencies. This forces developers that want to use our config to manually download each and one of our dependencies. This is obviously very cumbersome and kind of misses the whole point of a shared config. This is even more true when it comes to monorepos like the official [MY COMPANY] repository, in which every single package has the same huge list of ESlint dependencies even though we have, right next to them, a single shared ESlint config. There are ways of bypassing this limitation (@rushstack/eslint-patch etc...) but they come with their own limitations and are considered as "patches" rather than actual features.
However, in August 2022, the ESlint team came up with a new config system called ESlint Flat Config. This new config system allows (among other things) for a shared config to declare its dependencies as dev (or regular) dependencies, and include them in the config file (by importing them as a node package). This is obviously great news for us, since it basically means all of the issues listed in the previous paragraph will be solved. However, we need to give time to ESlint configs and plugins packages to adapt to this new config system, and for now. For instance, the typescript-eslint package created an issue on the 08/11 to update their config system.
This means that for now, we need to stick with the old config and its peer dependencies, and keep an eye on the package updates until the new ESlint config system is mature enough for us to migrate to it.
Some references to read more about this subject :
- https://github.com/eslint/eslint/issues/3458
- https://eslint.org/blog/2022/08/new-config-system-part-1/
- https://eslint.org/blog/2022/08/new-config-system-part-2/
- https://eslint.org/blog/2022/08/new-config-system-part-3/
- https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new
Answered By - souyahia
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.