Do not take the numbers on this site on faith. Here is how to get them in your own project.

Why bother

Because "tree-shakeable" is a claim, and yours is the only bundle that matters. A library can be perfectly tree-shakeable and still land whole in your build — one import * as, one lookup by string, one barrel file, and the bundler stops being able to prove what is unused.

How

Build twice and subtract. First, ng build --configuration production as you have it today; note the gzip size of the entry chunks. Then add the icon and build again. The difference is what the icon cost you — not what anyone promised.

To see why a number is what it is, build with --stats-json and open the result in any bundle analyser. What you are looking for is whether the icon catalog appears whole: if you imported bellIcon and the output mentions icons you never named, something is anchoring the registry.

The usual culprit is name="bell" with provideIconCatalog(ANIMATED_ICONS). That path is a convenience and it is documented as such: a lookup by string cannot be tree-shaken, so it pulls the whole catalog on purpose. If you want the small number, pass the icon by value with [iconDef].

What to expect

Measured in CI on every push against the published package:

  • One icon — around 13.7 KB gzip net over an empty app, engine included.
  • Ten icons — around 15.2 KB. The engine is paid once; each icon adds roughly 0.17 KB.
  • The whole catalog via name= — over 100 KB. That is the trade, and it is the reason the catalog is opt-in.

If your numbers are far above these, the difference is in your build, not in the package — and the stats file will say where.