使用TypeScript和webpack在项目之间共享代码

17

我想在两个TypeScript项目之间共享代码。我不想将共享代码发布到NPM,只想将共享代码放在一个项目中,并在另一个项目中使用它。我正在使用Webpackawesome-ts-loader。当前文件夹结构(简化)如下:

/devroot/
  mainProject/
    tsconfig.json
    src/
      shared/
        SomeSharedTypes.ts
  apiProject/
    tsconfig.json
    webpack.config.js
    src/
      UseSomeSharedType.ts

UseSomeSharedType.ts 中,我想要能够从 SomeSharedTypes.ts 导入类型。
我尝试了一个显而易见的解决方案,像这样:
import {SharedType} from '../../mainProject/src/shared/SomeSharedTypes'

但是TS编译器给了我这个错误:

TS6059:文件'/devroot/mainProject/src/shared/SomeSharedTypes.ts'不在'rootDir' '/devroot/apiProject'下。期望'rootDir'包含所有源文件。

2个回答

17

我从这篇Medium文章中得到的第一个想法是使用TypeScript的非相对模块导入功能。这将允许我像这样编写我的导入:

import {SharedType} from '@foo/SomeSharedTypes'

使用文章中描述的技术,我向我的tsconfig.json添加了paths配置:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@foo/*": ["../mainProject/src/shared/*"],
    },
    "rootDir": "./",
    ...
  }
}

如同文章建议的那样,对于使用awesome-typescript-loader的用户,我需要修改webpack.config.js文件并添加一个resolution插件:

然后,按照文章的建议,在使用awesome-typescript-loader的情况下,我不得不修改我的webpack.config.js文件来添加一个resolution插件:

(Two possible translations depending on context)
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');
. . .
  resolve: {
    extensions: ['.js', '.json', '.ts'],
    plugins: [
      new TsConfigPathsPlugin(),
    ],
  }

重要提示:此插件需要放置在文件的 resolve/plugins 部分,而不是根级别的 "plugins" 部分!如果您将解析器插件放错位置,您将会得到以下错误:

resolver.ensureHook 不是一个函数

上述步骤让我继续执行了下去——TypeScript 现在能够找到我的文件了!——但是在 webpack 的执行过程中仍然遇到了同样的错误:'rootDir' is expected to contain all source files.

经过更多的搜索,我在 这个 StackOverflow 回答中 找到了一个解决方案:TS 不是使用单一的 rootDir 配置,而是有一个允许多个根目录的设置,名为 rootDirs。我从 tsconfig.json 中删除了我的 rootDir 设置,添加了一个 rootDirs 设置:

"rootDirs": [
  "./",
  "../mainProject",
],

接下来,我在另一个项目的TypeScript文件中遇到了webpack错误:

模块解析失败:意外的标记(3:15)

您可能需要一个适当的加载程序来处理此文件类型。

经过又一小时的故障排除,我发现需要告诉webpack加载程序关于我的新共享文件夹。像这样:

const path = require('path');
. . .
  rules: [
    {
      test: /\.[jt]sx?$/,
      loader: "awesome-typescript-loader",
      include: [
        __dirname,
        path.resolve(__dirname, "../mainProject/src/shared/")
      ],
      exclude: /node_modules/
    },

非常好!这个解决方案的好处是,我可以重构我的文件夹结构而不更改源代码。我只需要更改 tsconfig.jsonwebpack.config.js 即可。

我承认我对使用 webpack 和 TypeScript 还很陌生,所以可能有比上述方法更好的解决方案...但上述方法对我有效!

在此分享解决方案,以便下一个开发人员更容易找到。


在我向 tsconfig.json 添加了 "baseUrl"/"paths" 以及 loader: 'awesome-typescript-loader' plugins: [ new TsConfigPathsPlugin() ]之后,似乎已经足够了,rootDirsinclude 不再必要。至少 tscwebpack 都成功了。 - Martynas Jusevičius
2
我想插一嘴并感谢你指出“rootDirs” - 这解决了我的很多问题,因为我并不知道那是一个选项! - Alex Gelinas

0

我强烈推荐使用Nx workspace management工具,因为它是专门用来解决这些设置问题的。您可以在存储库中创建一个库,然后在任何地方导入它(请参见:https://nx.dev/angular/tutorial/08-create-libs)。我和我的团队现在已经严重依赖Nx超过6个月了,无法想象没有它如何管理TypeScript存储库,请试试!https://nx.dev

如果您不能使用Nx,则可以模拟实现代码共享的方式:

  1. 创建一个新文件夹
  2. 添加一个index.ts文件,其中包含应从库外部访问的所有内容
  3. 在您的tsconfig.json-> compilerOptions-> paths中添加一个条目,该条目指向您的库的index.ts
  4. 通过您在tsconfig.json中指定的导入名称导入共享代码

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接