🧩 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)