angular-cli: The `ng serve` command is unusually slow in v12

🐞 Bug report

Command

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes, the previous version in which this bug was not present was 11.

Description

The ng serve command is unusually slow and considerably increase with the number of library (especially lazy loaded ones from what I experienced).

🔬 Minimal Reproduction

I privately shared a reproduction with @alan-agius4 (link here https://github.com/hadrien-toma/angular-12-perf-troubleshooting) and I am opening this issue here in order to track it properly and to not pollute the one I originally posted in (https://github.com/angular/angular-cli/issues/20713).

🔥 Exception or Error

No error.

🌍 Your Environment

Here is my package.json dependencies (@angular/core installed is 12.0.4).


    "@angular/animations": "^12.0.0",
    "@angular/cdk": "^12.0.4",
    "@angular/common": "^12.0.0",
    "@angular/compiler": "^12.0.0",
    "@angular/core": "^12.0.0",
    "@angular/forms": "^12.0.0",
    "@angular/material": "^12.0.4",
    "@angular/platform-browser": "^12.0.0",
    "@angular/platform-browser-dynamic": "^12.0.0",
    "@angular/platform-server": "^12.0.0",
    "@angular/router": "^12.0.0",

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 11
  • Comments: 22 (2 by maintainers)

Most upvoted comments

@hadrien-toma, as mentioned earlier this appears to be caused by TypeScript incremental API, as it can also be reproduced using tsc directly.

I strongly suggest that you share a reproduction with the TypeScript team so that they can investigate from their end.

@hadrien-toma thanks a lot for sharing the project and all the details, reproductions like these are super helpful and crucial to get to the bottom of issue.

Myself and @JoostK are looking at this and it appears that this performance issue is only manifested during watch mode.

We’ll keep you posted.

@JoostK Yes, in fact, in the shared reproduction all the libs are already --buildable and --publishable, it should have changed something? 😣

In the monorepo however libraries are consumed using path mappings directly to the sources and not the built versions. Therefore, they become part of the application compilation unit.

I am not saying that compiling your libraries before will solve your issue. But in general that is expected to improve the build times of the application.

Also, libraries uses a different build pipeline and therefore compiling libraries as part of an application isn’t technically correct and it can result in inconsistencies.

I had to migrate the application back to the 11.0.3 This is a disaster(

Does anybody handle it already?

I’m having the same issue with build and serve times in a new nx monorepo project and the time oscillates between 120s to 380s. My configuration:

Dev config:

"development": {
    "buildOptimizer": false,
    "optimization": false,
    "vendorChunk": true,
    "extractLicenses": false,
    "sourceMap": true,
    "namedChunks": true
}

---------------------------------------------------------

Angular CLI: 12.0.0
Node: 12.22.1
Package Manager: npm 6.14.12
OS: linux x64

Angular: 12.0.0
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, material, material-moment-adapter
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1200.0
@angular-devkit/build-angular   12.0.0
@angular-devkit/core            12.0.1
@angular-devkit/schematics      12.0.1
@schematics/angular             12.0.1
ng-packagr                      12.0.2
rxjs                            6.6.7
typescript                      4.2.4

Hi @hadrien-toma,

I did take a look at the reproduction and it appears that the root cause is caused by TypeScript’s incremental builder program. In the CLI for watch mode we use ts.createEmitAndSemanticDiagnosticsBuilderProgram.

In TypeScript 4.3 there were several performance improvements related to the above mentioned API. However, in your case the rebuild are still as slow as using TS 4.2. However, the first cold build timing improved quite a lot.

Cold Build with 57a192c6f834458ad1bd7db5c2a8669e07774690

TypeScript version duration
4.2 200065ms
4.3 28607ms

Rebuild that changes libs/ng/apps/***/public/route/src/lib/modules/ng-apps-***-public-route.module.ts

~code removed on request by issue author~

The above change will cause slow incremental build times. By adding the highlighted import, 138 additional TS source files are marked as affected by the change. The main reason for this is because in your case your libraries are not really libraries which have been build prior to be consumed by the application, they are just application files in a seperate directory. From compilation perspective your entire monorepo, is one gigantic application because of the architecture used here.

Using the profiler, I noticed that the most time consuming methods are inside the TypeScript compiler. Screenshot 2021-06-11 at 12 30 16

Therefore I then tried to build your application using TypeScript compiler directly (which uses createEmitAndSemanticDiagnosticsBuilderProgram API under the hood) and did see similar results, were the first build took 12s while a rebuild (which was triggered by the above mentioned change) took 163s.

tsc --watch --project apps/***/tsconfig.app.json
[12:48:43 PM] Starting compilation in watch mode...
[12:48:55 PM] Found 0 errors. Watching for file changes.
[12:49:00 PM] File change detected. Starting incremental compilation...
[12:51:43 PM] Found 0 errors. Watching for file changes.

Therefore, following the above outcome from the investigation I suggest you share this reproduction with the TypeScript team, where ideally you remove all related NX and NG tooling to keep it as minimal as possible.

Here is a copy of my original post:

Kind of same troubles for me…

I totally recreated my project step by step in v12.0.4 and what I noticed is that adding one of my lazy loaded route added ~5min to my “ng serve” (~1min before this addition).

Also this is not linked to Material in my case: I took the time to completely rewrite the Material part with the new way of using it, hopping this will change something, but it doesn’t.

@alan-agius4 I shared with you the newly created project in v12 in case you would like to take a look (https://github.com/hadrien-toma/angular-12-perf-troubleshooting). The last commit is the one introducing the big change, some stats on my laptop:

Commit 75dfc25b64141bc2a29ee5d972393e28b2865c87: 19948ms (bases, serving was acceptable) Commit 6f510ccefcab2eaa0571387caec0deebe66301f3: 62411ms (adding libs, serving becomes quite heavy) Commit 57a192c6f834458ad1bd7db5c2a8669e07774690 : 427616ms (adding the aforementioned lazy loaded route, serving becomes enormous) PS: I tried to add other lazy loaded libs and the additons just increase the time… I reached to get 30min for an ng serve for only 7 routes…

Edits In fact, my production build time seems to not be affected (stable around 7min). My development environment is the following:

        "development": {
          "buildOptimizer": false,
          "optimization": false,
          "vendorChunk": true,
          "extractLicenses": false,
          "sourceMap": false,
          "namedChunks": true
        }

So I don’t really understand why the build and the serve operations are impacted so differently, I expected the build time to not be faster than the serve upside_down_face. Now I realize my issue is likely to not be linked to this one thinking.