需要使用 Yarn 3 和 TypeScript 在 monorepo 中设置 eslint 的帮助

sou*_*hia 6 node.js typescript eslint yarn-workspaces yarnpkg-v2

我一直在绞尽脑汁地尝试在我的 monorepo 中设置 ESlint 配置。我使用 Yarn 3.2.4 作为包管理器。这是包含示例项目的 GitHub 存储库。。这是项目结构:

\n
/monorepo\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /configs\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /eslint\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /jest\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /prettier\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 /typescript\n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /packages\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 /mypackage\n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .eslintrc.js\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\n
Run Code Online (Sandbox Code Playgroud)\n

具有以下内容:

\n
    \n
  • /monorepo/package.json(根包.json)
  • \n
\n
/monorepo\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /configs\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /eslint\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /jest\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /prettier\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 /typescript\n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tsconfig.json\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 /packages\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 /mypackage\n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .eslintrc.js\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 package.json\n\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • /monorepo/configs/eslint/package.json
  • \n
\n
{\n  ...,\n  "workspaces": [\n    "configs/*",\n    "packages/*"\n  ],\n  "scripts": {\n    "lint": "yarn workspaces foreach -pt run lint"\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • /monorepo/configs/eslint/index.js只是我的普通 eslint 配置文件,扩展并使用上面列出的 eslint 配置包

    \n
  • \n
  • /monorepo/packages/mypackage/package.json

    \n
  • \n
\n
{\n  ...,\n  "name": "@monorepo/eslint-config",\n  "main": "index.js",\n  "peerDependencies": {\n    "eslint": "^8.27.0",\n    ...\n    * other eslint plugins / configs *\n    ...\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • /monorepo/packages/mypackage/.eslintrc.js
  • \n
\n
{\n  ...,\n  "devDependencies": {\n    "@monorepo/eslint-config": "workspace:*",\n    "eslint": "^8.27.0",\n    ...\n    * other eslint plugins / configs *\n    ...\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在有了这个配置,它就可以工作了。然而,我发现真正烦人的是我需要在我的 mono 存储库的每个包中指定 eslint 配置/插件依赖项。如果我尝试将这些依赖项放在devDependencieseslint-config 包中,然后从mypackage包中删除它们(只留下eslint为开发依赖项),我会收到以下错误消息:

\n
Error: Failed to load plugin \'@typescript-eslint\' declared in \'.eslintrc.js \xc2\xbb @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.\n\nRequired package: @typescript-eslint/eslint-plugin\nRequired by: /path/to/monorepo/packages/mypackage/\n\nRequire stack:\n- /path/to/monorepo/packages/mypackage/__placeholder__.js\nReferenced from: /path/to/monorepo/.yarn/__virtual__/@monkvision-eslint-config-virtual-abbbf308a5/1/configs/eslint/index.js\n    at Function.require$$0.Module._resolveFilename (/path/to/monorepo/.pnp.cjs:16089:13)\n    at Function.resolve (node:internal/modules/cjs/helpers:108:19)\n    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)\n    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)\n    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)\n    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)\n    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)\n    at _normalizeObjectConfigDataBody.next (<anonymous>)\n    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)\n    at _normalizeObjectConfigData.next (<anonymous>)\n
Run Code Online (Sandbox Code Playgroud)\n

所以我的问题是:有没有办法只声明一次 ESlint 插件依赖项(在配置项目中),而不是在我的 monorepo 的每个包中?

\n

抱歉发了这么长的帖子,并提前致谢。

\n

sou*_*hia 15

好吧,在阅读了几天关于这个主题的文章之后,我想我对这个主题有了一个很好的概述。

这实际上是一个与ESlint相关的问题,与yarn工作空间无关。这实际上是 ESlint 的一个限制,它强制共享配置使用对等依赖项。然而,有一些解决方法/未来的解决方案。对于感兴趣的人,我将复制/粘贴我在工作中为我的团队写的消息:


由于目前 ESlint 工作方式的限制,共享 ESlint 配置需要将其依赖项(例如其他配置、插件等)指定为对等依赖项。这迫使想要使用我们的配置的开发人员手动下载我们的每个依赖项。这显然非常麻烦,并且有点错过了共享配置的全部意义。对于像官方 [MY COMPANY] 存储库这样的 monorepos 来说更是如此,其中每个包都具有相同的巨大 ESlint 依赖项列表,即使我们在它们旁边有一个共享的 ESlint 配置。有多种方法可以绕过此限制(@rushstack/eslint-patch等...),但它们有自己的限制,并被视为“补丁”而不是实际功能。

然而,在 2022 年 8 月,ESlint 团队提出了一个名为 ESlint Flat Config 的新配置系统。这个新的配置系统允许(除其他外)共享配置将其依赖项声明为开发(或常规)依赖项,并将它们包含在配置文件中(通过将它们作为节点包导入)。这对我们来说显然是个好消息,因为这基本上意味着上一段列出的所有问题都将得到解决。然而,我们现在需要给 ESlint 配置和插件包一些时间来适应这个新的配置系统。例如,typescript-eslint 包在 08/11 上创建了一个问题来更新其配置系统。

这意味着现在我们需要坚持使用旧的配置及其对等依赖项,并密切关注软件包更新,直到新的 ESlint 配置系统足够成熟,我们可以迁移到它。

阅读有关此主题的更多信息的一些参考资料: