如何为第三方react javascript模块设置@types,以便可以从打字稿访问它并将其与webpack打包在一起?

时间:2019-02-22 20:46:05

标签: javascript typescript npm webpack

有一个第三方的全JavaScript npm scoped软件包,我们将其称为@foo,其中包含一个名为bar的模块。我想在我的打字稿.tsx文件中使用react组件@ foo / bar / X。尝试import X from '@foo/bar/X'时,我立即遇到“找不到模块”的问题。如何使用@types打字稿来解决此问题,以解决模块X并使Webpack正常运行?

1 个答案:

答案 0 :(得分:0)

我的起点是关于如何使用打字稿https://www.typescriptlang.org/docs/handbook/react-&-webpack.html使用react和webpack的介绍。但是,上述说明不能解决我要使用的react组件没有@types的问题。所以我的第一步是我需要添加@types。

作用域模块@ foo / bar有一个重要的细微差别,那就是它将其所有子组件分解为单个子模块,例如@ foo / bar / X,@ foo / bar / Y和@ foo / bar /具有@ foo / bar的Z本身没有任何功能。我们将看到,这是一个重要的细微差别,这比我不必在我的打字稿中导入作用域模块要复杂得多。

nice blog post here关于如何将普通javascript导入打字稿的。不幸的是,所提议的方法存在缺点。即,在src / @ typings中添加“ index.d.ts”的想法有两个问题:

  1. 它仅适用于本地运行Typescript编译器(tsc)。也就是说,通过允许tsc从您本地的“ .d.ts”文件中解析模块,这将使tsc满意,但是webpack仍然会失败,并且找不到模块。
  2. 提出的方法并没有教我如何处理作用域模块,这些模块对@types下的文件夹的命名方式有不同的规则

无论尝试哪种方法,我都知道我需要在我的打字稿文件中包含此导入语句:

import X from '@foo/bar/X';

ReactDOM.render(
    <X/>,
    document.getElementById("example")
);

在某个地方,我需要在“ .d.ts”声明文件(如index.d.ts)中包含以下内容,这很明显:

declare module '@foo/bar';
declare module '@foo/bar/X';

但是运行“ webpack”会产生Module not found: Error: Can't resolve '@foo/bar/X'

我决定使用此标志运行打字稿编译器(tsc),以查看tsc尝试解析模块的可能位置。

tsc --traceresolution 

使用traceresolution标志,我可以看到一些非常有趣的东西:在tSC搜索的node_modules / @ types下的位置是非常不可预料的(因此是webpack的搜索位置,因为webpack遵循与tsc相同的规则)。期望在node_modules/@types/foo__bar下找到我的index.d.ts文件。没错,对于范围包,您不能有node_modules/@types/@foo/bar/index.d.ts。相反,您必须在名为foo__bar的@types下使用具有DOUBLE UNDERSCORE的单个文件夹。

基于此知识,我创建了@ types / foo__bar。我将package.json从@ foo / bar模块复制到@ types / foo__bar。我清除了@types不需要的所有脚本和其他无用的东西,并将其剥离为:

{
  "name": "@types/@sfoo/bar",
  "version": "2.6.0",
  "peerDependencies": {
    "react": "^16.3",
    "react-dom": "^16",
    "styled-components": "^3"
  },
  "dependencies": {
...
  },

  "engines": {
    "node": ">=6"
  },
  "gitHead": "ac0288aaa47a4f15e56db3a5eff4424fb7905419",
  "main": "",
  "types": "index"
}

但是还有另一个问题!即使在tsc可以解析我的@types之后,webpack仍然产生module not found: can't resolve @foo/bar。那么,为什么Webpack找不到它呢?再次,我发现了一个可以向我展示更多内容的标志:

webpack --verbose

但是在这里我运气不佳,因为webpack规则就像模块解析的打字稿规则一样。但是从--verbose输出中,我确实注意到webpack感兴趣的一个文件是node_modules/@foo/bar/index.js。但是,bar模块缺少任何index.js,因为它实际上只是一个围绕@ foo / bar / X等子模块的空封闭模块。我不知道这是Webpack的错误还是Webpack的功能,但是将一个空的index.js添加到了node_modules / @ foo / bar pacified webpack中,而我的简单示例现在可以与加载时浏览器中显示的组件X一起使用HTML页面。