π§© How to Lazy Load Standalone Angular Components as Separate JS Files β Ideal for On-Demand Icons
When you're building a large Angular app β especially with many SVG icons or visual components β loading all of them up front bloats your bundle and hurts performance.
What if you could:
- Split each icon into its own JS chunk
- And load them only when needed?
Thanks to Angular standalone components and dynamic import()
, you can do exactly that.
This guide shows you how to create truly separate JS files (chunks) for each component, and load them on demand β perfect for things like icon libraries, feature flags, or infrequently used UI blocks.
β TL;DR
You can:
- Create standalone components (e.g., SVG icons)
- Load each via
import()
- And Angular will split each into its own JS file
- That JS chunk will only be downloaded when needed
Result? Blazing-fast first load π
π Use Case: Load SVG Icons Only When Used
Letβs say you have a large icon set like:
/icons/ search-icon.component.ts home-icon.component.ts settings-icon.component.ts
Instead of importing them all and inflating your bundle, you'll:
β
Turn each into a standalone component
β
Dynamically load the needed icon at runtime
β
Let Angular generate a separate JS file (chunk) for each
π Step-by-Step: Lazy Load as Separate Chunks
1. Create a Standalone SVG Component
// icons/search-icon.component.ts import { Component } from '@angular/core'; @Component({ standalone: true, selector: 'app-search-icon', template: \` <svg width="24" height="24" fill="none"> <path d="..." /> </svg> \`, }) export class SearchIconComponent {}
π No
NgModule
. It's a fully standalone component.
2. Use import()
to Load It On Demand
In your host component:
import { ViewChild, ViewContainerRef } from '@angular/core'; @ViewChild('iconHost', { read: ViewContainerRef }) vcRef!: ViewContainerRef; loadSearchIcon() { import('./icons/search-icon.component').then(({ SearchIconComponent }) => { this.vcRef.clear(); this.vcRef.createComponent(SearchIconComponent); }); }
In your HTML:
<button (click)="loadSearchIcon()">Show Search Icon</button> <ng-container #iconHost></ng-container>
π§
import()
triggers Angularβs code-splitting β so the icon is excluded from the main bundle and gets its own JS file.
3. Build with Optimization On
Run this command:
ng build --configuration production
Now check your output folder (dist/
), and you should see something like:
main.<hash>.js runtime.<hash>.js polyfills.<hash>.js icons-search-icon-component.<hash>.js β
π‘ That last file is your lazy-loaded icon, automatically split into a separate JS chunk by Angular.
π― Why This is Awesome for SVG/Icon Libraries
- β¨ Avoid bloating your main bundle
- β‘ Only load the icon when itβs actually needed
- π§© Each icon is encapsulated as a component
- π¦ Tree-shaking friendly β unused icons never load
π Side Note: What About Libraries?
This setup also works in Angular libraries (e.g., in an Nx workspace or shared icon lib), with a few conditions:
- β
Keep your icon components
standalone: true
- β
Import them with a direct relative path using
import()
- β Do not re-export them in the libraryβs
public-api.ts
β or Angular will include them in the main bundle
Want a full working example inside a library setup? Drop a comment β it's just a minor adjustment.
π§ͺ Bonus: Verify the Chunk
Want to confirm that the icon really became a separate JS file? Use Webpackβs bundle analyzer:
ng build --configuration production --stats-json npx webpack-bundle-analyzer dist/YOUR_APP_NAME/stats.json
Youβll see a separate chunk like:
icons-search-icon-component.<hash>.js
π§ Final Thoughts
Angularβs support for standalone components + native dynamic import()
makes it incredibly easy to split your code.
You now have:
- Fully isolated, lazy-loadable components
- Chunk-per-icon architecture
- Faster startup times and less JS downloaded up front
No extra tooling. No webpack config hacks. Just clean Angular.
π Summary
Feature | Supported? |
---|---|
Lazy-load individual SVG/icon components | β Yes |
Force each into its own JS chunk | β Yes |
Works with standalone components | β Yes |
Use import() with direct file path | β Yes |
Use inside an Angular library (with caveats) | β Yes |
Re-export via public-api.ts | β No |
Thanks for reading! π
Top comments (0)