在开发环境中运行typescript monorepos推荐的方法是什么?

vlf7wbxs  于 2023-03-04  发布在  TypeScript
关注(0)|答案(1)|浏览(126)

上周,我一直在将一个非常大的单一存储库(npm/typescript)重构为monorepo(yarn/lerna/typescript),刚开始的时候转换非常容易,我只是将文件重构到它们各自的文件夹中,并更新导入。
真正的痛苦开始于我开始在"开发"中尝试运行monorepo的不同方式(热重新加载/观看)模式。我真的很想避免每一个变化的每一个包(遗憾的是,就目前而言,它们都是相互依赖的)我使用Lerna引导项目并安装模块,正如我所看到的,Lerna将文件夹链接到Node_Modules,这意味着每一个更改都会在所有repos中自动更新。我已经尝试了几种方法,我真的需要指导如何继续或者标准是什么。
问题:
我有一个monorepo,其中包含3个带有服务类的包/项目,以及1个使用这些包的CLI包。当我使用命令对旧的monolithic repo运行CLI命令时:

ts-node --transpiler sucrase/ts-node-plugin --project tsconfig.json --require tsconfig-paths/register bin/cli.ts

它在内部传输所有必要的(引用的)ts文件,并在500ms-1秒内执行。这是一个可以接受的传输时间,我希望保持。我的第二个问题是我使用了tsconfig路径,这意味着我每个包都有一个tsconfig文件。我希望保持它们,但在最坏的情况下,我将不得不用相对路径替换它们。
以下是我的解决方案:
1.用tsc-watch运行每个目录,将package.json主条目指向dist/index.js,然后完成它。这样做的问题是tsc的编译/传输时间。编译源文件大约需要500ms-1s。d.ts文件生成对于每个包花费至少1.5 - 2秒,且在tspath之上花费另外500ms来替换我试着用babel-watch代替tsc-watch,它对于JS编译来说甚至更快,但是没有生成类型。
1.使用相同的文件运行上面提到的相同命令。我尝试了这个命令,它似乎工作正常,但我不知道如何解析嵌套软件包的tsconfig路径。例如,软件包CLI将使用相对tsconfig解析其路径,然后CLI将找到本地软件包Transpiler(本地文件夹链接到node_modules),它有自己的路径集,我不知道如何指定。在这种情况下,我会牺牲ts路径来获得真正快速的开发迁移时间。在这种情况下,我会将package.json main指向src/index.ts,这会使构建变得困难,因为每次构建生产项目时都需要替换它(但这与步骤1相同)。
我使用AWS JS SDK monorepo作为指导和参考。
项目结构:

packages
    - cli *(depends on transpiler)*
    - transpiler *(depends on common and statements)*
    - statements *(depends on common)*
    - common *(depends on nothing)*
package.json
tsconfig.json
yshpjwxd

yshpjwxd1#

在我之前对你的问题写了评论之后,我实际上做了一些进一步的挖掘,发现了这篇很棒的文章Boost your productivity with TypeScript project references,并决定给予一试。
为了给予一些关于我的monorepo项目Slickgrid-Universal的统计数据,我在monorepo中有17个包,我使用Lerna-Lite时没有使用任何工具,在每次测试运行之前,我删除了所有dist/文件夹,然后比较了两种方法
1.执行lerna run命令大约花费了1 m30秒
1.使用TypeScript引用执行tsc -b花费了18秒
哇,我不能我已经错过了这个tsc -b(或--build)与TypeScript引用它是5倍快,只是哇,这也包括声明文件(d.ts)。我们还可以添加监视模式(也注意到它的性质是增量的,所以没有必要添加--incremental

tsc --build ./tsconfig.packages.json --watch

我还尝试了另一个测试,我想看看当我将新属性添加到common包中的现有接口时,在监视模式下传播类型需要多长时间(这是我最大的包,有数百个接口),并等待着看接口花了多长时间才反映在我的前端包中,花了10秒才在我的编辑器中显示出来,还不错但我真的以为(希望)更低的值。事实上,10秒与我之前在每个包中使用lerna watchtsc --incremental的实现非常相似,所以我没有看到这方面的多少增益。真实的的增益实际上是在第一个干净的构建上,18 sec vs 1 m30 sec对我的整个monorepo包括类型是惊人的快相比之前。
我们能快点吗?
可能还有另一种方法,我读过但从未真正尝试过,那就是简单地进行类型检查(这是ViteJS和ESBuild正在做的),而不通过命令tsc --noEmit生成声明文件。我不确定,但我认为使用这种方法,至少构建一次类型,然后在监视模式下使用--noEmit可能会更好。我不确定这在monorepo结构中是否真的能很好地工作,因为从mono的另一个包导入必须经过那个包的package.json,我假设这将需要类型存在,以便能够在编辑器中使用TypeScript。我认为这个新的选项2.是我从现在开始使用的。
注意,我还想知道这个tsc -b是否可以与其他工具如TurboRepo或Nx一起使用。我没有使用这些工具,但我猜它可能不起作用。我猜使用这些工具,您仍然需要在每个包中使用单独的tsc命令。如果与缓存一起使用,使用这些工具可能仍然更快,因为您只需要构建您更改的包。但是tsc -b --incremental也是相当快的。
编辑
在重构代码并创建PR之后,我发现了一些需要记住的事情

  • 使用TypeScript References和Composite时需要注意的一点是,由于其结构,我们只能使用一个配置来执行此操作,这意味着我们无法使用不同的设置运行多个不同的构建版本(即:CJS,ESM),至少我不这么认为。

1.我决定仍然保留我原来的lerna watch,它在每个包中使用tsc --incremental,原因有两个
1.我还监视SASS文件,并希望为所有文件扩展名(.ts、.scss)保留一个Lerna监视。
1.在已更改的包中使用lerna watchtsc --incremental的时间与从根目录运行tsc -b --watch的时间大致相同,因此,如果我在开发中没有获得速度,那么我宁愿保留已设置的单个lerna手表,而不是使用多个手表(1x tsc手表,多个SASS手表,因为我有几个SASS主题)

  1. lerna watch似乎比tsc --watch占用更少的资源(内存/CPU使用率),至少在Windows上是这样。注意,单个tsc监视器仍然比每个包有多个tsc监视器要好一个数量级
    1.这最后三点可能与您的项目无关,tsc -b仍然是前进的方向
    不管这最后3点,我仍然在启动lerna watch之前在根目录中运行tsc -b,因为它非常快,而且我需要在开始开发时存在类型。然而,当这完成后,我只是简单地依赖于lerna watch来运行tsc --incremental的软件包上的变化。它不是最快的,但它仍然比我以前有很多。也许通过这种方法,我可以只使用lerna watchtsc --noEmit进行类型检查(将来有更多时间时,我可能给予一下)
    我还发现另外这篇文章Using TypeScript Project References with ts-loader and Webpack非常有帮助,信息量也很大

相关问题