Developing an Angular app typically goes off without a hitch. But as your project expands over time, you might start seeing an unexpected warning:

Budget exceeded warning example

At first glance, this might trigger a few questions:

  • Is there a way to turn this warning off?
  • What steps can I take to figure out what's inflating my bundle size?
  • And what exactly is a budget in this context?

Time to address those!

Understanding the Angular budget

Angular uses the term "budget" to describe the maximum size your application can reach while still being considered acceptable.

Say you're okay with a 2MB cap on your app's bundle—anything larger would raise eyebrows, and crossing 5MB would be seen as a clear problem.

With this concept in mind, you have the ability to tune this behavior directly through the budget configuration in your angular.json file:

{
  // ...
  "architect": {
    "build": {
      "configurations": {
        "production": {
          "budgets": [ ]
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

But budgets come in several flavors, and you can define limits for each one:

  • ... the whole application
  • ... each bundle that gets produced
  • ... how much JavaScript is needed just to get the app bootstrapped
  • ... the total size of all scripts, or any single script
  • ... the footprint of any component’s stylesheet
  • ... the size of any individual file

For every category, you decide the cutoff point at which a warning or an error should be raised.

The values you set accept multiple measurement styles, including bytes (b), kilobytes (kb), megabytes (mb), and even percentages (%) when you provide a starting baseline.

As an example, this budget triggers a warning when the total app size goes beyond 500kB, and an error if it exceeds 1MB by more than 50%:

"budgets": [
  {
    "type": "all",
    "baseline": "1mb",
    "maximumWarning": "500kb",
    "maximumError": "150%"
  }
]
Enter fullscreen mode Exit fullscreen mode

Getting rid of the warning, the quick'n dirty way

Armed with that insight, the quickest and simplest route to silencing the warning is to raise the threshold to a larger value.

You might deliberate over what that number should be for your specific project, pick a ridiculously high figure, or drop those lines altogether:

"budgets": [
  {
    "type": "initial",
    "maximumWarning": "999mb",
    "maximumError": "999mb"
  },
  {
    "type": "anyComponentStyle",
    "maximumWarning": "999mb",
    "maximumError": "999mb"
  }
],
Enter fullscreen mode Exit fullscreen mode

That said, this approach may only mask the issue rather than truly fix it.

Getting rid of the warning, the proper way

Before you can optimize anything, you need to know what’s holding you back and what has room for improvement.

Bundle optimization works the same way: let’s take a closer look at what’s inside our bundle!

Generating the proper bundle

During the build process for your app, Angular creates multiple JS chunks that together make up your entire page.

By building in production mode, you also get the Angular compiler’s optimizations, which help produce a smaller bundle.

Visualizing that optimized output is an effective way to see exactly what ships in your final build while filtering out anything that was only needed for development.

Yet, if you attempt to visualize that bundle at this point, you’ll run into a problem: Angular doesn’t emit source maps or named chunks when in production mode, so there’s nothing useful to look at.

We can work around this by simply enabling those options on the bundle we want to inspect:

~$ ng build --source-map=true --named-chunks=true
Enter fullscreen mode Exit fullscreen mode

Visualizing your bundle

With the bundle in place, we can now pick a fitting tool to examine it.

One such option, among others, is source-map-explorer, which describes itself in the following manner:

The source map explorer determines which file each byte in your minified code came from. It shows you a treemap visualization to help you debug where all the code is coming from.

That sounds quite useful! Let's fetch the NPM package and include it in our dev dependencies:

~$ npm i -D source-map-explorer
Enter fullscreen mode Exit fullscreen mode

If you prefer to keep everything within your Angular workflow, the Builder To Run Source Map Explorer integrates it seamlessly—no extra setup needed, and you can invoke it direct from your Angular application through the builder.

Meanwhile, we can add a shorthand npm script to package.json so this task runs quickly:

{
  // ...
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "sme": "ng build --source-map=true --named-chunks==true && source-map-explorer dist/<YOU_APP_NAME>/**/*.js"
  },
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Assuming all went according to plan, your browser will launch a fresh tab showing a view similar to this:

SME example

This view gives you a clear picture of what ends up inside your app bundle and how much space each piece occupies.

Keep in mind the screenshot comes from a minimal Angular application; your own project will likely be far more intricate.

Taking actions

With a clear view of the bundle's contents, you can start trimming it down. A few common culprits might explain why it's larger than anticipated:

  • Perhaps a library weighs far more than expected, and you overlooked a leaner alternative way to include it
  • Or maybe a package that should remain a development dependency has slipped into the production set
  • And so on

Good practices

The smartest move is to dodge this headache altogether by planning ahead, saving you both time and frustration.

As you build out your project ...

  • ... double-check which libraries you bring in and confirm whether each one is truly essential
  • ... exploit Angular's built-in features to lazy load modules, keeping the initial bundle lean

Another option worth weighing is adopting standalone components, since this approach obligates you to spell out every dependency a component relies on, helping you pull in only what's absolutely needed.


Those tips should give you some useful takeaways, so happy coding out there!

Sources


Photo by Callum Parker on Unsplash