应该如何配置 VSCode 以支持 Lerna Monorepo?

Posted

技术标签:

【中文标题】应该如何配置 VSCode 以支持 Lerna Monorepo?【英文标题】:How Should VSCode Be Configured To Support A Lerna Monorepo? 【发布时间】:2020-01-12 04:42:52 【问题描述】:

我有一个 lerna monorepo 包含很多包。

我正在努力实现以下目标:

    确保 VSCode 提供从一个包到另一个包的正确导入建议(基于包名称,而不是相对路径)。 确保我可以“打开定义”这些导入之一并被带到该文件的 src。

对于 1. 我的意思是,如果我在 package-a 中导航代码并开始键入由 package-b 导出的函数,我会收到一个建议,该建议将触发添加导入:`import example from '包-b'。

对于 2. 我的意思是,如果我 alt/单击由 'package-b' 导出的函数的名称,同时从导入它的不同包中导航文件,我将被带到 '/packages/namespace/ package/b/src/file-that-c​​ontains-function.js',

我的 (lerna) monorepo 采用标准结构,例如这里是一个“组件”包,发布为 @namespace/components

- packages
    - components
       - package.json
       - node_modules
       - src
         - index.js
         - components
           - Button
             - index.js
             - Button.js
       - es
         - index.js
         - components
           - Button
             - index.js
             - Button.js

请注意,每个组件都由一个目录表示,以便在必要时可以包含其他组件。在此示例中,packages/components/indexButton 导出为命名导出。文件被编译到包的/es/ 目录。

默认情况下,VSCode 为导入提供自动建议,但它被这种结构混淆了,例如,如果 monorepo 中的不同包需要使用Button,它将自动建议以下所有导入路径:

packages/components/src/index.js packages/components/src/Button/index.js packages/components/src/Button/Button.js packages/components/es/index.js packages/components/es/Button/index.js packages/components/es/Button/Button.js

但是这些都不合适,因为它们将被呈现为从导入文件到导入文件的相对路径。在这种情况下,以下导入是正确的导入:

import  Button  from '@namespace/components'

将排除项添加到项目的jsconfig.json 对建议的路径没有影响,甚至不会删除/es/* 的建议:


  "compilerOptions": 
    "target": "es6",
  ,
  "exclude": [
    "**/dist/*",
    "**/coverage/*",
    "**/lib/*",
    "**/public/*",
    "**/es/*"
  ]

使用“compilerOptions”显式添加路径也无法建立文件之间的正确关系:


  "compilerOptions": 
    "target": "es6",
    "baseUrl": ".",
    "paths": 
      "@namespace/components/*": [
        "./packages/namespace-components/src/*.js"
      ]
    
  ,

目前 Cmd/单击来自不同包的导入无法打开任何内容(未找到定义)。

我应该如何配置 VSCode 以便:

    VSCode 使用命名空间包作为导入值自动建议从 monorepo 中的其他包导入。 使用“开放定义”将我带到该文件的 src。

根据要求,我在根目录中有一个 babel 配置:

const  extendBabelConfig  = require(`./packages/example/src`)

const config = extendBabelConfig(
  // Allow local .babelrc.js files to be loaded first as overrides
  babelrcRoots: [`packages/*`],
)

module.exports = config

延伸:

const presets = [
  [
    `@babel/preset-env`,
    
      loose: true,
      modules: false,
      useBuiltIns: `entry`,
      shippedProposals: true,
      targets: 
        browsers: [`>0.25%`, `not dead`],
      ,
    ,
  ],
  [
    `@babel/preset-react`,
    
      useBuiltIns: true,
      modules: false,
      pragma: `React.createElement`,
    ,
  ],
]

const plugins = [
  `@babel/plugin-transform-object-assign`,
  [
    `babel-plugin-styled-components`,
    
      displayName: true,
    ,
  ],
  [
    `@babel/plugin-proposal-class-properties`,
    
      loose: true,
    ,
  ],
  `@babel/plugin-syntax-dynamic-import`,
  [
    `@babel/plugin-transform-runtime`,
    
      helpers: true,
      regenerator: true,
    ,
  ],
]

// By default we build without transpiling modules so that Webpack can perform
// tree shaking. However Jest cannot handle ES6 imports becuase it runs on
// babel, so we need to transpile imports when running with jest.
if (process.env.UNDER_TEST === `1`) 
  // eslint-disable-next-line no-console
  console.log(`Running under test, so transpiling imports`)
  plugins.push(`@babel/plugin-transform-modules-commonjs`)


const config = 
  presets,
  plugins,


module.exports = config

【问题讨论】:

您介意分享一下您是如何构建项目的吗? 您是否有一个全局的jsconfig.json 文件或在每个packages/ 目录中都有一个jsconfig.json 文件? @mathayk 每个包都包含一个/src/ 目录。 Babel 将这些文件编译到 /es/ 目录中,因此每个包都包含 /src//es/ 目录。将此添加到问题中。 @mathayk 我有一个全局 jsconfig.json 文件。 感谢您的回答!您能否将您的babel.config.js 文件添加到问题中。你使用的是哪个 babel 版本?你有一个或多个 babel 配置文件吗? 【参考方案1】:

在你的情况下,我会结合使用lerna 和yarn workspaces。 运行yarn install 时,所有包都链接在@namespace 下的全局node_modules 文件夹中。有了它,您将获得 IntelliSense。

我在这里设置了一个示例存储库:https://github.com/flolude/***-lerna-monorepo-vscode-intellisense

您只需将"useWorkspaces": "true" 添加到您的lerna.json

lerna.json


  "packages": ["packages/*"],
  "version": "0.0.0",
  "useWorkspaces": "true"

剩下的只是适当的命名:

global package.json


  "name": "namespace",
  // ...

package.json of your component package


  "name": "@namespace/components",
  "main": "src/index.js",
  // ...

package.json of the package that imports the components


  "name": "@namespace/components",
  "main": "src/index.js",
  "dependencies": 
     "@namespace/components":"0.0.0"
  
  // ...

然后您可以执行以下操作:

import  Component1  from '@namespace/components';

// your logic

自动从@namespace导入

不幸的是,我找不到使用 javascript Monorepo 在 VSCode 中完成这项工作的方法。但是你可以做一些事情:

    使用 Typescript (tutorial, other tutorial) 使用module-alias 将import from '@namespace/components' 添加到文件顶部 使用Auto Import 分机

【讨论】:

谢谢。你已经成功了一半。 “开放定义”肯定是有效的。但是导入建议仍然使用相对路径,例如打开/packages/website/src/index.js,删除导入并键入“Comp”。你会看到 VSCode 提供了一个导入建议,但是如果你选择它,它添加的导入将是 import Component1 from '../../components/src/component1',而不是 import Component1 from '@namespace/components' 好吧,这个没有简单的答案。但我已经编辑了我的答案以提供一些选项 真的很抱歉。我想在你的情况下,我会尝试切换到打字稿 无需道歉。不幸的是,这实际上并不可行。我们的代码库工作量太大。 如果您设置一次,实际上并没有更多的工作。但我不会判断,因为我对您的项目没有足够的了解。我希望我至少能帮上一点忙:)【参考方案2】:

编辑:最新版本的 VSCode 打破了这一点。

我终于设法让它可靠地工作。你需要为你的 monorepo 中的每个包创建一个单独的jsconfig.js,例如:

monorepo root/packages/some-package/jsconfig.json:

  "compilerOptions": 
    "target": "es6",
    "jsx": "preserve",
    "module": "commonjs"
  ,
  "include": ["src/**/*.js"],
  "exclude": ["src/index.js"]

请注意,我已排除 src/index.js 文件,因此它不会作为该包中的导入建议提供。

此设置似乎可以实现:

Intellisense 从包中导入建议,而不是使用相对路径。 转到定义以找到 monorepo 中其他包的来源。

VSCode 最近一直很不稳定,但它似乎正在工作。

请注意,这适用于仅 JavaScript 的 monorepo(不是 Typescript)。

【讨论】:

以上是关于应该如何配置 VSCode 以支持 Lerna Monorepo?的主要内容,如果未能解决你的问题,请参考以下文章

VSCode配置LaTeX Workstation以支持中文

如何设置 GitHub 操作以发布 Lerna Monorepo

如何配置 webpack 以从其他 lerna 包中转译文件(从 create-react-app 中弹出)

Lerna bootstrap 不链接本地依赖项?

让VSCode支持gbk编码

如何配置 VS Code 以启用 .json 文件的代码完成(jsonschema 支持)?