Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ng serve command is unusually slow in v12 #21116

Closed
1 of 15 tasks
hadrien-toma opened this issue Jun 11, 2021 · 22 comments
Closed
1 of 15 tasks

The ng serve command is unusually slow in v12 #21116

hadrien-toma opened this issue Jun 11, 2021 · 22 comments

Comments

@hadrien-toma
Copy link

hadrien-toma commented Jun 11, 2021

🐞 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 (#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",
@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 11, 2021

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.

@alan-agius4 alan-agius4 added needs: investigation Requires some digging to determine if action is needed severity4: memory/performance area: @ngtools/webpack labels Jun 11, 2021
@ngbot ngbot bot added this to the needsTriage milestone Jun 11, 2021
@alan-agius4
Copy link
Collaborator

@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.

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Jun 11, 2021

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.

@alan-agius4 alan-agius4 removed needs: investigation Requires some digging to determine if action is needed area: @ngtools/webpack labels Jun 11, 2021
@ngbot ngbot bot removed this from the needsTriage milestone Jun 11, 2021
@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 11, 2021

I see, thank you very much for your time and help. So what I plan to do is:

  • to make a public reproduction of this issue in an Nx workspace and raise an issue on Nx side hoping a solution will pop overthere 🍀.
  • to share this reproduction in an issue on the TypeScript repo. I think I will not be able to remove all Nx and Ng tooling unfortunately...

As a side note, a workaround I am thinking of at the moment : run chokidar on my side with a custom/crafted watch configuration and run nx:affected commands when a changes occurs, maybe the incremental build will be more comfortable than the current very slow ng serve 🤔 🤞...

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Jun 11, 2021

to share this reproduction in an issue on the TypeScript repo. I think I will not be able to remove all Nx and Ng tooling unfortunately...

All you need to keep is the libs and apps folders and tsconfig files.

@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 11, 2021

Ah, thank you! So I will do that 🤝 !

@JoostK
Copy link
Member

JoostK commented Jun 11, 2021

@hadrien-toma FYI, Nx has buildable libraries that result in each library having its own compilation unit.

@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 11, 2021

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

@JoostK
Copy link
Member

JoostK commented Jun 11, 2021

Oh I was expecting it to not use that (haven't had a look at the repro yet)

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Jun 11, 2021

@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.

@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 11, 2021

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.

Yeap, that's why I supposed it was not linked, the fact that they are buildable and publishable is more link to the final delivery process.

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.

Yeap, and thanks to the nx:affected commands, I think there is something to investigate on this strategy.

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.

Interesting, I understand, thanks for the details.

@hadrien-toma
Copy link
Author

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

I just made another example without specifying that lazy loaded routes are --buildable and --publishable (by default they are not) but the duration of the ng serve remains the same.

@hadrien-toma
Copy link
Author

As a workaround for the moment I am using chokidar to watch specifically inside my libs and apps, a change re-run nx build command (so using its cache) and then re-run angular-http-server.

Even if the browser is not updated automatically, the time to get the app working the first time is around 70s, which allows me to work again even if not really comfortable...

@hadrien-toma
Copy link
Author

hadrien-toma commented Jun 13, 2021

I have done another example in v11 and the serve durations are fine so in a "user" point of view, this slow behavior is likely to be considered as a regression (I am not saying this is linked to Angular, it could be on Nx or TypeScript side).

@alan-agius4
Copy link
Collaborator

@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
Copy link
Author

Hey @alan-agius4 yes I will try to do a sharable smaller reproduction asap 😬

@jonastg
Copy link

jonastg commented Jun 21, 2021

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

@hadrien-toma
Copy link
Author

Thanks for sharing @jonastg, I will not have time to work on it recently, do you mind to share a reproduction on your side?

@glebmachine
Copy link

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

Does anybody handle it already?

@alan-agius4
Copy link
Collaborator

@glebmachine, you might be experiencing a different issue. Please file a new issue including a reproduction or at the very minimum a CPU profile. You can also share the project privately like @hadrien-toma did for this issue.

Regarding this specific issue, there is not much we can do since this is caused by an issue in TypeScript incremental API, which @hadrien-toma will/will report to TypeScript and provide a minimal reproduction based on his problematic project.

@alan-agius4
Copy link
Collaborator

Closing since for this particular issue is not actionable from our end since it's a bug inside of the TypeScript compiler.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jul 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants