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

fix(@angular-devkit/build-angular): fix budget checks #16268

Merged
merged 3 commits into from Dec 9, 2019

Conversation

dgp1130
Copy link
Collaborator

@dgp1130 dgp1130 commented Nov 22, 2019

Fixes #15792.

This turned out to be a little more complicated than expected due to the combination of a few different problems resulting in broken budget checks.

  • File sizes were previously computed in a Webpack plugin, which is executed during certain lifecycle hooks. I needed to move this to run after the build when all the necessary file size information is known. The first commit refactors the size computations without any significant changes to the output.
  • Files listed as lazy: true or inject: false in the app dev's angular.json file were included in the initial bundle, even though these resources must be loaded asynchronously. The second commit filters out files which were marked asynchronous from the initial bundle.
  • Differential builds were included in the same size, so the main size was including both the ES2015 and ES5 sizes together, which isn't what the user would want. The third commit updates the relevant budgets to output two sizes, one for each differential build, rather than including them together.

I made separate commits performing each of these steps individually to make the logic a little easier to follow and understand.

@dgp1130 dgp1130 added the target: patch This PR is targeted for the next patch release label Nov 22, 2019
@dgp1130 dgp1130 added this to the v9-blockers milestone Nov 22, 2019
@dgp1130 dgp1130 requested a review from clydin November 22, 2019 21:48
@dgp1130 dgp1130 self-assigned this Nov 22, 2019
@dgp1130 dgp1130 force-pushed the budgets branch 4 times, most recently from e9a2408 to 4a9543d Compare November 26, 2019 21:27
@dgp1130 dgp1130 force-pushed the budgets branch 3 times, most recently from ec36dc8 to 3b91986 Compare December 2, 2019 17:21
@dgp1130 dgp1130 removed this from the v9-blockers milestone Dec 3, 2019
@dgp1130 dgp1130 force-pushed the budgets branch 3 times, most recently from 4e4730e to c43a5a9 Compare December 4, 2019 19:26
…be post-build

Refs angular#15792.

This provides access to all the size information necessary because all build steps have already completed. This commit is roughly a no-op because it simply moves the budget checks (for different builds) to be executed post-build.

The lone exception is the AnyComponentStyle budget. Component stylesheet files are not emitted after the build is completed, so there is no size information to work with. Instead, these budgets are checked during a separate plugin (exected for different builds **and** non-differential builds).
… bundle budget.

Refs angular#15792.

Static files listed in `angular.json` were being accounted in the `initial` bundle budget even when they were deferred asynchronously with `"lazy": true` or `"inject": false`. Webpack belives these files to be `initial`, so this commit corrects that by finding all extra entry points and excluding ones which are explicitly marked by the application developer as asynchronous.

One edge case would be that the main bundle might transitively depend on one of these static files, and thus pull it into the `initial` bundle. However, this is not possible because the files are not present until the end of the build and cannot be depended upon by a Webpack build step. Thus all files listed by the application developer can be safely assumed to truly be loaded asynchronously.
…ial builds separately

Fixes angular#15792.

Previously, budgets would include content for both versions of a differential build. Thus the `initial` budget would count content from the ES5 **and** ES2015 bundles together. This is a very misleading statistic because no user would download both versions. I've updated the budget calculators to take this into account and generate size values for both builds which are then checked independently of each other.

The only calculators I changed are the `InitialCalculator` (for computing `initial` bundle sizes) and `BundleCalculator` (for computing named bundles). Since budgets are handled by Webpack for builds without differential loading, the `initial` bundle will always have those two sizes. The `BundleCalculator` might reference a bundle which does not have differential loading performed (such as a CSS file), so it emits sizes depending on whether or not multiple builds were found for that chunk.

Most of the other calculators don't really need to take differential loading into account. `AnyScriptCalculator` and `AnyCalculator` already apply on a file-by-file basis, so they generate sizes for both build versions already. `AnyComponentStyleCalculator` only applies to CSS which does not have differential builds.

The wierd ones here are `AllCalculator` and `AllScriptCalculator` which reference files with and without differential builds. Conceptually, they should be separated, as a "total" budget specified by an app developer probably wanted it to mean "the total resources a user would have to download", which would only be one differential build at a time. However, I don't see a good way of identifying which assets belong to which differential build. Even if an asset belongs to a chunk with differential builds, we don't know which build takes which assets into account. I decided to leave this for the time being, but it is probably something we should look into separately.

Since budgets take differential loading into account, users might reasonably want to set different budgets for different builds (ie. "initial-es2015 bundle should be capped at 100k, but initial-es5 bundle can go to 150k"). That's more of a feature request, so I also left that out for a future PR.
@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 Jan 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Initial bundle logs and budget warning are working wrong
5 participants