VSCode如何配置为支持Lerna Monorepo?

时间:2019-09-10 12:11:21

标签: javascript import visual-studio-code lerna monorepo

我有一个lerna monorepo,其中包含很多软件包。

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

  1. 确保VSCode提供从一个软件包到另一个软件包的正确导入建议(基于软件包名称,而不是相对路径)。
  2. 确保可以对其中一种导入文件进行“打开定义”,并导入到该文件的src中。

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

对于2。我的意思是,当我从已导入文件的另一个包中浏览文件时,如果我按住/单击“ 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/index导出Button作为命名导出。文件将被编译到程序包的/es/目录中。

默认情况下,VSCode为导入提供自动建议,但是这种结构使它感到困惑,并且,例如,如果monorepo中的其他软件包需要使用Button,则会自动建议以下所有导入路径:< / p>

  • 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,以便:

  1. VSCode使用命名空间的软件包作为导入值自动建议从monorepo中的其他软件包进行导入。
  2. 使用“打开定义”将我带到该文件的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

2 个答案:

答案 0 :(得分:3)

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

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

intellisense preview

您只需将"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自动导入

不幸的是,我找不到使用Java语言Monorepo在VSCode中实现此功能的方法。但是您可以做一些事情:

  1. 使用打字稿(tutorialother tutorial
  2. 使用module-alias
  3. import {} from '@namespace/components'添加到文件顶部 add import to file
  4. 使用Auto Import扩展名 auto import

答案 1 :(得分:0)

我终于设法使它可靠地工作了。您需要为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)。