【问题标题】:Investigating long TypeScript compile times调查较长的 TypeScript 编译时间
【发布时间】:2016-04-14 13:14:42
【问题描述】:

我正在调查为什么我的 Angular 2.0 TypeScript 项目的编译时间在相对较短的时间内从大约 4 秒变为大约 15 秒。

我遇到了非常有用但似乎没有记录的--diagnostics 开关。

例如,这是我现在在我的项目上运行 tsc --noEmit --diagnostics 时得到的结果:

Files:             231
Lines:           50872
Nodes:          170067
Identifiers:     65994
Symbols:       7712123
Types:          407677
Memory used:   600554K
I/O read:        0.43s
I/O write:       0.00s
Parse time:      1.13s
Bind time:       0.34s
Check time:     10.17s
Emit time:       0.00s
Total time:     11.64s

这是我在项目的早期版本上运行相同命令时得到的结果。

Files:             197
Lines:           30882
Nodes:          124208
Identifiers:     46201
Symbols:       5856945
Types:           10989
Memory used:    80412K
I/O read:        0.03s
I/O write:       0.00s
Parse time:      0.60s
Bind time:       0.27s
Check time:      0.93s
Emit time:       0.00s
Total time:      1.79s

Types 的数量增加了很多,Check time 的数量也增加了。

是否可以从--diagnostics 获得更详细/详细的输出?

NodeJS v4.4.3,TypeScript v1.8.10。这是我的tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",

    "noImplicitAny": false,
    "noEmitOnError": false,

    "experimentalDecorators": true,

    "emitDecoratorMetadata": true,
    "removeComments": false
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "typings/main.d.ts",
    "typings/main"
  ]
}

【问题讨论】:

    标签: typescript angular


    【解决方案1】:

    看来我找到了我的罪魁祸首。我很难做到;我的过程:

    1. 找到导致编译缓慢的提交。逐个提交历史并检查编译时间。
    2. 注释掉更改的代码,直到找到有问题的行。

    在有问题的提交之前,我一直得到大约 2-4 秒的编译时间,而在提交之后 - 13-17 秒。

    在我的例子中,我有一个类,带有一个 accessTokenGetter 字段,它在构造函数中被初始化:

    export class JwtConfig {
        //...
        accessTokenGetter: () => Observable<string>;
        //...
          constructor(private config?: IJwtConfig) {
              // ...
              this.accessTokenGetter = this.config.accessTokenGetter || (() => Observable.of(null));
          }
    }
    

    初始化|| (() =&gt; Observable.of(null)); 的第二部分导致缓慢。将其注释掉或添加类型注释可以缩短编译时间。由于 Observable 是通用的,TypeScript 编译器似乎需要一个提示来缩小它需要做的一些类型检查。我的初始化现在显示为:

    //...
    this.accessTokenGetter = this.config.accessTokenGetter || (() => Observable.of(<string>null));
    //...
    

    Observable.of(null as string)) 似乎也可以完成这项工作。在其他几个地方添加类型注释可以加快编译速度。

    希望这对某人有所帮助。

    不过,如果编译器中有一个工具可以更快地得到答案 - 我很乐意听到它。

    【讨论】:

    • 谢谢,我遇到了同样的问题。避免它的学习规则:尽可能添加类型注释
    • 哇,这太疯狂了。如果有一种自动化的方法可以追踪此类缓慢的推理,那就太好了。
    • 您可以从git bisect 中受益,并将编译时间作为枢轴/条件。只需几分钟即可将 1000 次提交一分为二。设置时间可能不到一个小时,您可以在以后的调查中重复使用它
    • 运行 tsc --noEmit --diagnostics 导致检查时间为 0.00 秒。我想是因为结果缓存在tsconfig.tsbuildinfo,所以在运行诊断之前一定要删除这个文件。
    【解决方案2】:

    我可以从 15 秒加快编译过程。到 6-7 秒。通过更改这一行代码:

    // slow:
    // ...
    .flatMap((receivedObj: MyType) => {
        let nextObservable: Observable<MySecondType> = this.dependingPut(receivedObj);
        return nextObservable || new Observable((observer) => {
                observer.next(undefined);
            });
    });
    
    
    // fast:
    .flatMap((receivedObj: MyType) => {
        let nextObservable: Observable<MySecondType> = this.dependingPut(receivedObj);  
        return nextObservable || new Observable<MySecondType>((observer) => { // <--- use the generics!
                observer.next(undefined);
            });
    });
    

    来自 Typescript 手册 (https://www.typescriptlang.org/docs/handbook/generics.html):

    function identity<T>(arg: T): T {
        return arg;
    }
    
    // ...
    
    let output = identity("myString");  // type of output will be 'string'
    

    "请注意,我们不必在角度中显式传递类型 括号 (),编译器只查看值“myString”,并且 将 T 设置为其类型。虽然类型参数推断可能是一个有用的工具 为了使代码更短且更具可读性,您可能需要明确 像我们在上一个示例中所做的那样,当 编译器无法推断类型,这可能在更复杂的情况下发生 例子。”

    就我而言,它没有失败;类型推断只花了很长时间(顺便说一句,它也消耗了大量内存)。 在您开始构建解决方法之前,请返回您的修订历史并尝试识别错误的修订。为确保编译器是罪魁祸首,请使用--diagnostics 选项。如果返回的统计信息返回较高的“检查时间”值,请检查您的代码是否存在缺失类型。

    【讨论】:

      【解决方案3】:

      对我来说,减速是由于像 import "./file.ts"; 这样的导入。删除 .ts 扩展后,速度提高了 90%:import "./file";

      【讨论】:

        【解决方案4】:

        已知编译器很慢,您可以在监视模式下使用编译器tsc -w 或切换到webpackts-loader,这会暴露transpileOnly 选项(无需耗时检查)。

        【讨论】:

        • 谢谢。我们使用gulp-typescript (npmjs.com/package/gulp-typescript) 来观察变化。它支持增量编译。即使观看,我也始终能获得 12 到 18 秒的构建时间。但是过去的构建速度更快,并且没有添加太多代码,我们才刚刚开始。一定是某些变化导致了这个问题,但是逐个提交搜索会非常耗时。
        • 我试过 gulp-typescript 和内置的 Intellij Idea 编译器,但是太慢了,每次更改后大约 8 秒,无法接受。现在我正在使用带有 transpileonly 选项的 webpack 和 ts-loader,重新编译时间约为 0.5s。
        【解决方案5】:

        在我的例子中,编译时间大约是 15-30 秒。在 tsc --noEmit --diagnostics 命令之后,我注意到我正在构建 2k 个文件。解决方案是从node_modules 文件夹中排除所有文件:

        {
          "compilerOptions": {...},
           "exclude": [
             "node_modules"
           ]
        }
        

        最好也排除typings 文件夹。

        【讨论】:

        • 是的,同意。但是当我开始遇到问题时,我已经排除了两者。关于类型,我不太确定 - 取决于您如何设置项目,即如果您不使用三斜杠引用 (/// &lt;reference ..),您可能需要保留部分类型子树 - 因为我'在我的情况下已经完成 - 我只排除节点的类型(typings/main)。
        猜你喜欢
        • 2017-08-14
        • 2012-10-06
        • 2014-04-06
        • 1970-01-01
        • 1970-01-01
        • 2017-05-25
        • 1970-01-01
        • 2014-11-25
        相关资源
        最近更新 更多