You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
application builder generates many initial chunks #26307
I just migrated a small project to v17 and the application builder.
The ng build command generates 13 initial (i.e. not lazy-loaded) bundles.
I don't know if it's expected or not, but if it is, I don't understand the point of having so many initial bundles (the browser builder used to generate only 3).
Won't that automatically cause performance issues, given that browsers limit the number of concurrent requests to a given domain?
Describe the solution you'd like
Unless there is a good reason (that I'm currently missing) for so many bundles, I'd like the builder to generate fewer bundles: one for the polyfills (that could be cached for a long time) and one for the application for example.
If there is a good reason for so many bundles, please enlighten me :-)
@jnizet that how esbuild works. If you don't use http/2 it's would be drop in core web vitals. esbuild has open issue evanw/esbuild#207 but that is not implemented.
If you have http/2 setup that amount of chunks not an issue for you
OK. Too bad this isn't considered.
Couldn't the CLI, which is able to know which chunks are initial and which chunks are lazy-loaded, concatenate the initial chunks generated by esbuild?
@jnizet, containing the chunks will actually cause unnecessary code to be downloaded when navigating to a particular page.
Thus, for a performance perspective, having a lot of chunks should be better if using modern HTTP protocols. Although I do see that sometimes esbuild does generate super small chunks under 1 kb, but that is by esbuild design.
Concatenating chunks is definitely not something the Angular CLI should be doing. The bundler has the full context of how chunks should be split to download as code as possible.
@alan-agius4 when you say should be better, is this tested? How does esbuild know which pages where are thus creating chunks per page as webpack builder does?
Our website shows very bad performance after upgrading to angular 17. Lighthouse reports too many chained requests (150 chunks!):
before with angular 16 it was only 3 chunks and much better perf:
@elgerm you are right, but check my message above, try to upgrade your http to http/2 or better http/3 to get better performance, because http 1.1 has only 6 parallel connections in browser (that IS reason why concatenation in vendor chunk exist) while http/2 has 100
Which HTTP version are you using? In the case of HTTP 1 it is expected that there is a performance regression. It is also important mentioning that lighthouse should not be ran against a the local dev-server.
Hi guys, Lighthouse score went down from 70ish to 39.
We're behind cloudflare and have http3 enabled.
I switched back to 16 for now as this was unacceptable performance.
We get about 50k daily unique visitors from SE Asia, 33% use old devices and may find this unusable. Hence the question if it has been tested that so many small chunks don't degrade performance. There must be a penalty from loading and bootstrapping so many small chunks?
Angular went from module based to component based and now switched to esbuild that now generates a chunk per component/directive/pipe. There's 450 chunks in the dist folder 🤯.
Is it possible to go back to webpack build w 17?
Reacted by mihailik, Amany Zohair and Matthew Radcliffe
Our system creates waay more than those 150 chunks, it's actually at 240+ initial chunks (and 472 lazy chunks).
It is a rather large platform.
We went from 58 requests at initial load to over 400
It's still fast though, but I would like the preload to be reduced/delayed.
Tbh, though Angular is made for larger systems. It often feels like the really really large systems like this are not being tested out well. (not trying to bash here, just how it feels, I still love angular and the way it works a lot)
(Though it could just be that we should set things up differently, but there isn't much documentation about building a big system)
Angular 16: (still on webpack)
Angular 17: (no longer on webpack)
Reacted by Martin Zima, Javier Marín, mihailik and shuffler
Small project but a lot of dependencies that didn't combine their scripts which results in 698 chunks. I'm all for optimizing, but this is just weird. Especially seeing most are external dependencies which could very well be combined (or at least provide the option to do it). It currently serves 304 chunks for the first page of our project (most of it are external dependencies)
Reacted by Dmitry Zakharov, Martin Zima, Olaf Tietze and mihailik
what I really recommend to all as workaround is to use webpack for production and serve app for development with --forceEsbuild=true it run your project faster for development purposes, but production code build as previously using webpack. Some problems can be potentially found with background-image resolving difference, but in other cases all works same. We use it in our large app until esbuild not provide some solution for it.
This is also an issue for us. Looks like we may need to revert to using webpack for production as well, as the chaining of chunks on initial load is causing non-trivial performance issues.
First step is look what is in those small chunks. Lets say it's lots of lodash-es code, because lodash is 200 little functions. You could use commonjs lodash instead. esbuild will still delete unused code, but won't rip it apart anymore, as it can't guarantee side effect freeness.
If your 500 byte chunks contain simple strings, you could move those strings behind a barrel.
And if you import {lorem} from 'constants' it won't put const lorem = 'lorem string'; into a chunk, as esbuild doesn't split chunks for barrels (at least right now, could of course change)
So there are some ways to bend esbuild to your will.
Third option might be, to contribute to esbuild something like a minChunkSize option like webpack has.
Reacted by aiwha-dev, Dmitry Zakharov and bertrandg
Honestly I commented because the amount of chunks can be insane, and imho should be improved with better bundling/lazy loading.
but it is faster for us and working fine on chromebooks even. Cloudflare is caching it for free (and if you want you could even upload it to cloudflare workers)
Probably an Unpopular opinion, solutions because people are still on http1 should imho not happen. Use webpack then or upgrade your servers. Http 2 is from may 2015 and almost 9 years old now.
this issue is causing my colleagues to call me "the chunk man"
Reacted by noguespi, aiwha-dev, José Diogo, Dmitry Zakharov, Martin Zima, montella1507, Dimitar Todorov, Danilo Bassi, Amany Zohair, Ryan Craig Martin and 2 more
Honestly I commented because the amount of chunks can be insane, and imho should be improved with better bundling/lazy loading.
This is the main reason yes. I would already be happy if I could force every module to be a chunk, so that with lazy routes it at least only needs to do one request. But its difficult to probably see what belongs where. For standalone stuff it will likely be even more difficult and the only one to tell esbuild to do better, is angular itself. Since it could figure out a dependency tree that can be used to optimize it. Perhaps using routes to bundle them or something.
Probably an Unpopular opinion, solutions because people are still on http1 should imho not happen. Use webpack then or upgrade your servers. Http 2 is from may 2015 and almost 9 years old now.
You assume that every company owns their own servers or that their security/monitoring/etc tools can handle http2 already. Lets be real here, some bad admins can't be bothered or simply don't want to do anything about it. So having the option is always going to be of some benefit to people.
Third option might be, to contribute to esbuild something like a minChunkSize option like webpack has.
That or a dependency tree that can be used to figure out what is connected and can be bundled. With hot modules replacement / reloading, you already need to know what stuff needs to be reloaded with the changes you've made.
How can we post-process this exponential explosion of files?
Shipping ESBuild mode in Angular without built-in handling of chunks makes it highly disruptive.
Apart from complicating debugging/diagnostics in browser, it rakes up deployment and support risks couple orders of magnitude.
Network errors during deployment are way more probable, being 100x more transactional updates to the filesystem.
It becomes impossible to spot partial/incomplete deployment.
Every and all DevOps processes that were tuned to small number of files will grind nearly to halt
Anecdotal case:
we used to have Angular15 deployment taking 20-30 minutes using rsync to transfer dist/ files
by using webpack.optimize.MinChunkSizePlugin we lowered it to 3-4 minutes
now we're risking going back to excessively long deployments, even way worse
If Angular team is not ready to improve the situation at this point, can you folks please give us direction and help adding customisations/plugin/script to implement chunk coalescing at the project side?
angular-automatic-lock-bot commented on Apr 20, 2024
Activity
pumano commentedon Nov 10, 2023
@jnizet that how esbuild works. If you don't use http/2 it's would be drop in core web vitals. esbuild has open issue evanw/esbuild#207 but that is not implemented.
If you have http/2 setup that amount of chunks not an issue for you
alan-agius4 commentedon Nov 10, 2023
Indeed this is expected, this is becasue esbuild does cross chunk code motion which webpack does not, which results in a more smaller chunks.
When using HTTP/2 or HTTP/3 the number of files does not have any performance penalty.
jnizet commentedon Nov 10, 2023
OK. Too bad this isn't considered.
Couldn't the CLI, which is able to know which chunks are initial and which chunks are lazy-loaded, concatenate the initial chunks generated by esbuild?
alan-agius4 commentedon Nov 10, 2023
@jnizet, containing the chunks will actually cause unnecessary code to be downloaded when navigating to a particular page.
Thus, for a performance perspective, having a lot of chunks should be better if using modern HTTP protocols. Although I do see that sometimes esbuild does generate super small chunks under 1 kb, but that is by esbuild design.
Concatenating chunks is definitely not something the Angular CLI should be doing. The bundler has the full context of how chunks should be split to download as code as possible.
elgerm commentedon Nov 28, 2023
@alan-agius4 when you say
shouldbe better, is this tested? How does esbuild know which pages where are thus creating chunks per page as webpack builder does?Our website shows very bad performance after upgrading to angular 17. Lighthouse reports too many chained requests (150 chunks!):

before with angular 16 it was only 3 chunks and much better perf:
pumano commentedon Nov 28, 2023
@elgerm you are right, but check my message above, try to upgrade your http to http/2 or better http/3 to get better performance, because http 1.1 has only 6 parallel connections in browser (that IS reason why concatenation in vendor chunk exist) while http/2 has 100
alan-agius4 commentedon Nov 28, 2023
Hi @elgerm,
Which HTTP version are you using? In the case of HTTP 1 it is expected that there is a performance regression. It is also important mentioning that lighthouse should not be ran against a the local dev-server.
Esbuild performs code motion and splits the code based on it's usage which does create more chunks. This is described here: https://github.com/evanw/esbuild/blob/main/docs/architecture.md#code-splitting. Webpack has less chunks as it's unable to perform this sort of advanced optimization.
What is the lighthouse score before and now?
elgerm commentedon Nov 28, 2023
Hi guys, Lighthouse score went down from 70ish to 39.
We're behind cloudflare and have http3 enabled.
I switched back to 16 for now as this was unacceptable performance.
We get about 50k daily unique visitors from SE Asia, 33% use old devices and may find this unusable. Hence the question if it has been tested that so many small chunks don't degrade performance. There must be a penalty from loading and bootstrapping so many small chunks?
Angular went from module based to component based and now switched to esbuild that now generates a chunk per component/directive/pipe. There's 450 chunks in the dist folder 🤯.
Is it possible to go back to webpack build w 17?
pumano commentedon Nov 28, 2023
@elgerm its possíble to use webpack with 17 angular. Just use browser target, not browser-esbuild
sod commentedon Dec 8, 2023
The lighthouse block
Avoid chaining critical requestsis unfortunate reporting. You can only pick one:The old way (less & bigger chunks) is apparently worse as it's reported under
reduce unused javascriptwith a real penalty.But 152 files on initial load indeed does sound scary. Sadly esbuild has no
minChunkSizesetting like webpack does.aiwha-dev commentedon Jan 3, 2024
Our system creates waay more than those 150 chunks, it's actually at 240+ initial chunks (and 472 lazy chunks).
It is a rather large platform.
We went from 58 requests at initial load to over 400
It's still fast though, but I would like the preload to be reduced/delayed.
Tbh, though Angular is made for larger systems. It often feels like the really really large systems like this are not being tested out well. (not trying to bash here, just how it feels, I still love angular and the way it works a lot)
(Though it could just be that we should set things up differently, but there isn't much documentation about building a big system)
Angular 16: (still on webpack)

Angular 17: (no longer on webpack)

Martinspire commentedon Jan 23, 2024
Small project but a lot of dependencies that didn't combine their scripts which results in 698 chunks. I'm all for optimizing, but this is just weird. Especially seeing most are external dependencies which could very well be combined (or at least provide the option to do it). It currently serves 304 chunks for the first page of our project (most of it are external dependencies)
pumano commentedon Jan 23, 2024
what I really recommend to all as workaround is to use webpack for production and serve app for development with
--forceEsbuild=trueit run your project faster for development purposes, but production code build as previously using webpack. Some problems can be potentially found with background-image resolving difference, but in other cases all works same. We use it in our large app untilesbuildnot provide some solution for it.joewIST commentedon Feb 16, 2024
This is also an issue for us. Looks like we may need to revert to using webpack for production as well, as the chaining of chunks on initial load is causing non-trivial performance issues.
born2net commentedon Mar 2, 2024
same here, our server is http (not http/2) and so we need a way to keep total files same as webpack. Any updates? solutions?
sod commentedon Mar 2, 2024
First step is look what is in those small chunks. Lets say it's lots of lodash-es code, because lodash is 200 little functions. You could use commonjs lodash instead. esbuild will still delete unused code, but won't rip it apart anymore, as it can't guarantee side effect freeness.
If your 500 byte chunks contain simple strings, you could move those strings behind a barrel.
e.g. if you have constants like here:
you create a barrel like:
And if you
import {lorem} from 'constants'it won't putconst lorem = 'lorem string';into a chunk, as esbuild doesn't split chunks for barrels (at least right now, could of course change)So there are some ways to bend esbuild to your will.
Third option might be, to contribute to esbuild something like a
minChunkSizeoption like webpack has.aiwha-dev commentedon Mar 2, 2024
Honestly I commented because the amount of chunks can be insane, and imho should be improved with better bundling/lazy loading.
but it is faster for us and working fine on chromebooks even. Cloudflare is caching it for free (and if you want you could even upload it to cloudflare workers)
Probably an Unpopular opinion, solutions because people are still on http1 should imho not happen. Use webpack then or upgrade your servers. Http 2 is from may 2015 and almost 9 years old now.
LuisTovar0 commentedon Mar 4, 2024
this issue is causing my colleagues to call me "the chunk man"
Martinspire commentedon Mar 5, 2024
This is the main reason yes. I would already be happy if I could force every module to be a chunk, so that with lazy routes it at least only needs to do one request. But its difficult to probably see what belongs where. For standalone stuff it will likely be even more difficult and the only one to tell esbuild to do better, is angular itself. Since it could figure out a dependency tree that can be used to optimize it. Perhaps using routes to bundle them or something.
You assume that every company owns their own servers or that their security/monitoring/etc tools can handle http2 already. Lets be real here, some bad admins can't be bothered or simply don't want to do anything about it. So having the option is always going to be of some benefit to people.
That or a dependency tree that can be used to figure out what is connected and can be bundled. With hot modules replacement / reloading, you already need to know what stuff needs to be reloaded with the changes you've made.
mihailik commentedon Mar 20, 2024
How can we post-process this exponential explosion of files?
Shipping ESBuild mode in Angular without built-in handling of chunks makes it highly disruptive.
Apart from complicating debugging/diagnostics in browser, it rakes up deployment and support risks couple orders of magnitude.
Anecdotal case:
If Angular team is not ready to improve the situation at this point, can you folks please give us direction and help adding customisations/plugin/script to implement chunk coalescing at the project side?
angular-automatic-lock-bot commentedon Apr 20, 2024
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.