TypeScript [3.6.3] tsc --watch 非常慢(常规的tsc编译正常),

tv6aics1  于 4个月前  发布在  TypeScript
关注(0)|答案(9)|浏览(56)

对于我的代码库,使用--watch进行编译非常慢,有时会导致内存不足的段错误。不使用--watch进行编译需要4秒。
可以在这个仓库中重现:https://github.com/bryntum/chronograph/(公开可用,分支quark_master,修订版本c58bc18120021423c730c9c2287058066157b8fa)。
我发现了类似的问题,#34119,并尝试了其中的一些建议。值得注意的是,尝试启用

"declaration"               : true,
        "emitDeclarationOnly"       : true,

,这产生了251个编译错误。没有这些选项,所有编译都正常。
似乎增量编译使用了与正常编译不同的数据结构,或者可能是序列化格式不正确。

gxwragnw

gxwragnw1#

这可能解释了我的IDE(PhpStorm)经常处于“损坏”状态,出现错误的情况。请看截图 - npx tsc 不会产生任何错误,然而,IDE认为有很多错误。我相信这是因为IDE使用了增量编译,正如我们所看到的,它的行为与正常编译不同。

这是一个重大的可用性问题 - 我基本上不得不回到纯命令行编译,而不是使用IDE工具,这会立即将我带到出错的源代码行。
我认为这个问题应该优先处理,因为具有与正常编译产生不同结果的增量编译击败了前者的目的。基本上整个功能是损坏的,TS更改日志中最近的所有关于支持更快构建的说法都是不正确的。

7cwmlq89

7cwmlq892#

我也尝试了以下操作:

"declaration"               : true,
        "emitDeclarationOnly"       : true,
  • 并获得251个错误,其中大多数如下所示:
src/replica/Replica.ts:54:37 - error TS4020: 'extends' clause of exported class 'MinimalReplica' has or is using private name 'UnsafeProposedOrPreviousValueOfSymbol'.

54 export class MinimalReplica extends Replica(MinimalChronoGraph) {}
                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/replica/Replica.ts:54:37 - error TS4020: 'extends' clause of exported class 'MinimalReplica' has or is using private name 'WriteSeveralSymbol'.

54 export class MinimalReplica extends Replica(MinimalChronoGraph) {}
  • 结论:增量编译只能部分工作
qybjjes1

qybjjes13#

@samuraijack 故意让增量依赖于声明发射来决定构建最小依赖关系图。你的项目报告了与TypeScript@next相关的错误,所以我无法看到其中的内容,但我尝试使用它使用的3.4版本,由于循环性,声明需要很长时间,并且在声明发射运行中显示出来,这需要很长时间。
我建议你检查TypeScript@next是否已经改进,然后再回来。
如果你可以重现这个问题,那么@weswigham将是最适合告诉你如何改进的人。

nwsw7zdq

nwsw7zdq5#

仅供参考,即使你无法找出如何隔离可复现问题的方法,显式地在所有导出函数上写出返回类型通常可以提高性能。现在,当你能找出具体哪种返回类型可以节省最多的时间时,你就找到了一个可复现的问题。;)

ckocjqey

ckocjqey6#

@sheetalkamat 嗯,关键是增量编译会产生与常规编译不同的结果。这感觉像是增量编译过程中某个地方的严重设计限制(我猜是在声明序列化格式中)。我真的认为这两种编译模式应该产生完全相同的结果。TS团队是否承认这是一个问题?这是否应该作为一个单独的问题提出?
@weswigham 谢谢你提供的信息!

wgxvkvu9

wgxvkvu97#

你是否知道在 TypeScript 中,不使用声明 emit 和序列化的情况下,能否实现 --watch 构建?即使从理论上讲,如果它可以在 TypeScript 中实现。执行 emit 阶段的速度众所周知是相当慢的。在我 600k LOC 的项目中,仅运行 tsc 不使用 emit 需要大约 15-30 秒。使用 --watch 需要 20-60 分钟,其中 99% 的时间都花在了 transformTime/printTime/Emit 时间上。增量构建对此没有帮助。编辑一个文件可能导致重新编译需要另外 20 分钟,具体取决于编辑了哪个文件。

我不认为 --watch --noEmit 增量构建应该比仅使用 --noEmit 运行 tsc 更慢。如果 TypeScript 能够摆脱对依赖关系图的序列化声明,并依赖于其他东西,那将是非常好的。是否有可能依赖于 webpack?我不确定。我只需要了解 Typescript 内部的人的意见。

编辑:我已经尝试找出导致构建速度如此之慢的 emit 部分代码,但没有成功。大部分时间似乎都花在了制作 redux store typings(CombinedStore 的东西)上。我有很多 redux 模块。我无法隔离出导致问题的单个类型或文件,似乎只是代码量太大。

3okqufwl

3okqufwl8#

@grumd 我们使用 d.ts emit 来确定文件的形状是否发生了变化,以便我们只需要发出并重新查询仅更改了的文件或其依赖关系图的语义诊断。虽然这不能改变,但创建了一个名为 #41219 的文件,它可以帮助你传递一个新标志,表示不要生成 .d.ts 文件来确定文件形状的变化,并假设所有更改都影响整个依赖关系树,而不是局部更改。

这可能会帮助你,因为性能不会比再次运行 tsc 更糟糕,但可能更快,具体取决于你正在更改的文件,这可能导致需要刷新的文件子集更小。显然,在 watch/incremental 模式下对文件进行增量本地更改将比没有这个标志慢。

qrjkbowd

qrjkbowd9#

@sheetalkamat 在这方面,ts-server是如何工作的?在我的项目中,ts-server的重新编译似乎非常快(在VSCode中运行类型检查时),但是"tsc --watch"非常慢,而"tsc"还可以,但比VSCode TS重新编译要慢。我猜ts-server在某种程度上能够快速重新编译而不发出d.ts文件?为什么tsc --watch不能像ts-server一样使用相同的方法?

相关问题