VS代码:根路径中的“找不到模块”

时间:2019-03-08 12:47:26

标签: typescript visual-studio-code

我似乎无法用Visual Studio Code解决模块导入问题:

Cannot find module

我已经设置了sample repo to illustrate这个问题,其目录结构如下:

➜ tree -I node_modules
.
├── README.md
├── packages
│   ├── jsx
│   │   └── jsx.jsx
│   ├── tjs
│   │   └── tjs.js
│   ├── tscript
│   │   └── tscript.js
│   └── tsx
│       └── tsx.tsx
├── src
│   ├── entry.ts
│   └── localjs.js
└── tsconfig.json

我想使用babel-typescript进行此设置,但是我的调查表明该问题似乎是VSCode固有的,因此我将其排除在示例之外。

我已经尝试过pathstsconfig.json的所有排列方式,

    "paths": {
      "*": [
        "*",
        "packages/*",
        "packages/*/index.tsx",
        "packages/*/index.jsx",
        "packages/*/index.js"
      ],
      "$1": [
        "packages/$1/$1"
      ],
      "~/*": [
        "packages/*"
      ],
      "~/$1": [
        "packages/$1/$1"
      ],
      "*/$1": [
        "*/$1/$1",
        "packages/$1/$1",
        "*/packages/$1/$1"
      ]
    }

handbook的见解并不多。

2 个答案:

答案 0 :(得分:2)

current tsconfig.json的部分问题在于您正在使用include: [],因此配置中实际上不会匹配任何代码!

我找不到在示例配置中使用$1模式的任何示例,基于某些研究,我也不认为您尝试做的事情是可能的(另请参见:{ {3}})。您可以将{package}/{package}.jsx重命名为{package}/index.jsx吗?然后,您的路径配置可以简单地更改为:

    "paths": {
      "*": ["*", "packages/*"]
    },

答案 1 :(得分:1)

您已经获得answer from Wex的建议,建议您将文件重命名为具有基本名index和适当的扩展名,并使用映射"*"*: ["*", "packages/*"]。您在评论中提到,您宁愿避免重命名文件。除了避免重命名,我也不喜欢将很多文件命名为index.<some_extension>。在工作时,我自然会被我正在处理或正在获取报告的文件的基本名称吸引。可以通过目录区分具有几乎相同的基名的文件,但是我需要更多的认知工作来远离基名和路径,或者需要键盘上的更多工作才能完成。 (键入需要更长的时间。IDE只能提供这么多的帮助。)足以令人讨厌。

首先,让我们处理死胡同。我看不出有证据表明~中特别对待$1paths。我去检查了tsc的代码,发现那里没有任何可以处理这种模式的代码。可能是我错过了,但我认为它们只是不特别。另外,暂时忽略扩展名,您所需的映射是packages/<package_name>/<package_name>.ext。程序包名称出现了两次。因此,设置像"*": ["packages/*/*.ext"]这样的映射很诱人,但是TypesScript明确不允许这样做:tsc将给您一个关于出现在所需映射中的两个星号的错误。所以这也不是一个选择。

使用package.json

您可以通过在每个软件包中添加一个package.json字段来指向重命名问题,该字段带有一个"main"字段,该字段指向您希望被视为软件包入口的文件。例如,packages/jsx/package.json可以包含以下内容:

{
  "main": "jsx.jsx"
}

通过为所有其他软件包提供相似的文件,您可以将相关配置减少为:

"baseUrl": "",
"paths": {
  "*": ["packages/*", "*"]
},

或者您可以使用"baseUrl"指向您的软件包并完全忽略"paths"

"baseUrl": "packages/",

请确保您对package.json文件进行整理,因为如果这些文件中存在语法错误,tsc只会静默地忽略它们

添加index个文件以重新导出您的输入模块

另一种方法是使用索引文件,该索引文件简单地重新导出所有您希望作为包的入口点的文件。您当前拥有的文件将保留在此处,但将由经过适当设计的index文件引用。例如,packages/tsx/index.ts可以是:

export { default } from "./tsx";

如果所有软件包仅提供默认导出,则它们都可以遵循上述模式。否则,如果包导出多个符号而只想重新导出所有内容,则可以执行以下操作:

export * from "./myModule"; 

如果对所有软件包都执行此操作,则无需重命名任何内容,但是您将拥有其他index文件来满足"*": ["*", "packages/*"]映射。

在评论中,您提到使用Barrelsby之类的工具来生成index文件。我会担心对发展的影响。我可以看到在发布项目时生成了一个索引文件作为外观。因此,使用已发布项目的人们将处理Barrelsby或其他工具生成的文件。但是,在我看来,您的index文件在您的项目内部中。因此,为了在开发过程中获得适当的IDE支持,在贡献者开始贡献之前,索引文件必须已经存在。因此,贡献者必须先运行一些生成索引文件的内容,然后才能开始贡献。您还将生成与开发人员直接创作的文件并存的文件。我试图在我的项目中避免这种情况。

如果这是我的项目,并且我决定添加index文件来满足tsconfig.json映射,那么我的目标是构建我的项目,以便将index文件简化为一个文件。以上两种情况中的一种,然后跳过使用代码生成器。 (实际上,我打算针对上述两种情况中的第二种情况,因为我希望避免默认出口。有关默认出口问题的讨论,请参见here。)

单独映射包裹

如果其他解决方案对您的特定项目有问题,则可以为每个程序包提供一个映射:

"paths": {
  "jsx": ["packages/jsx/jsx.jsx"],
  "tjs": ["packages/tjs/tjs.js"],
  "tscript": ["packages/tscript/tscript.js"],
  "tsx": ["packages/tsx/tsx.tsx"],
},

这意味着每次添加新软件包时都添加一个映射。这是否可行取决于您的特定项目。您还可以将baseUrl设置为"packages/",并从上述所有路径中删除packages/

"baseUrl": "packages/",
"paths": {
  "jsx": ["jsx/jsx.jsx"],
  "tjs": ["tjs/tjs.js"],
  "tscript": ["tscript/tscript.js"],
  "tsx": ["tsx/tsx.tsx"],
},

尽管您仍然必须为每个程序包提供一个映射,但这使整个过程变得不那么繁琐。