Angular 12 'ng serve' builds apps slowly, almost like production builds
I've just migrated an app from Angular 11.2.7 to Angular 12. Everything runs fine, except that when I am developing and using 'ng serve', rebuild times are much, much slower now, to the point where it's frustrating.
I'm on an M1 iMac, using node 16.1.0, for what it's worth.
The machine was lightning fast at dev rebuilds (sub-second) before I moved to Angular 12. Now if I change just one line of code, even if I just change one letter in a console log, build times are 23 seconds, roughly 22 seconds of which are taken up with "phase: sealing".
I've also noticed that everything now runs from a minified 'main.js" even when ng serving. I seem to recall version 11 didn't do that, but ran individual un-minified components during dev. Which is to say, ng serve now seems to be doing something like full a production build every time I change anything. I think that's the root cause of the slowness, but I'm not sure.
So . . .
Should I still be using 'ng serve' for development in Angular 12?
Is there an option that needs to be set when you migrate, perhaps to turn off full minified rebuilds, to maintain the old build speed?
What is this 'sealing phase', anyway? It sounds like a production build term to me!
thanks
John
The angular cli got updated with v12 to have the development environment be more like production.
Or as they like to call it:
The aim of these changes is to reduce the configuration complexity and support the new "production builds by default" initiative.
Judging by what they've changed, you should update your angular.json
and update the projects.{PROJECT_NAME}.architect.build.defaultConfiguration
path:
"defaultConfiguration": "development"
Read more here
If you did not use the ng update
command, but manually updated using npm
, you need to run migrations. Specifically the material styling had some changes which can cause long build times if not migrated. To trigger these migrations run:
ng update @angular/cli --migrate-only --from 11 --to 12
If you're manually copying over bits and pieces from a clean angular.json (and you absolutely should do this), make sure you don't miss "defaultConfiguration": "development"
under serve
.
My previous angular.json didn't have this, which frankly could have been my mistake - or it might be a feature that came along after the fact. I was still getting a production build, which is super frustrating because it takes 3 minutes and nothing tells you which build it's doing.
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "angular12:build:production"
},
"development": {
"browserTarget": "angular12:build:development"
}
},
"defaultConfiguration": "development"
},
You'll know you have a dev build when:
- Viewing source in browser devtools shows your code and comments not all in one line.
- Lazy Chunk Files have long filenames like
default-src_app_common-crm_common-crm_module_ts.js
and not34.js
Also, personally I choose to turn off sourceMap
. It makes my compilation a lot faster and I can always enable if it I really need it.
Very important:
It looks like there's a 'bug-like behavior' with the migrations if you run them more than once. If the aot
setting is currently true then the migration will remove it (because the default is true, so it's redundant). However if you run it again (with the aot setting missing) then it will get written as false
and effectively disabled (because it thinks you're migrating from 11 where its absense meant false and it thinks you want it to remain false).
ng update @angular/cli --migrate-only --from 11 --to 12
So running migrations can actually give the illusion of speeding up the build, but in reality it is actually only disabling aot.
In other words don't run this if you've already run ng update
and look at your angular.json
file carefully.
I had to add the following to my config. My new app didnt seem to have any "development" configuration.
In angular.json
"configurations": {
"development": {
"optimization": false,
"outputHashing": "all",
"sourceMap": true,
"namedChunks": true,
"extractLicenses": false,
"vendorChunk": true,
"buildOptimizer": false,
"budgets": []
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ui:build"
},
"configurations": {
"development": {
"browserTarget": "ui:build:development"
}
},
"defaultConfiguration": "development"
}