Lazy Loading Ionic Pages to Shrink Initial Bundle Size
Learn how to split an Ionic/Angular app into lazy‑loaded modules, verify the resulting chunks, and understand the trade‑offs of extra HTTP requests.
13 Apr 2026, 12:41 UTC

Problem: Large initial JavaScript bundle slows first paint
When you generate a new Ionic starter with ionic start, every page lives in the root NgModule. The Angular CLI bundles all of that code into a single main.js file. On a typical medium‑sized app this can be 1–2 MB uncompressed, forcing the browser to download, parse, and execute code for pages the user may never visit.
Thesis: Lazy loading each page in its own NgModule reduces the initial bundle, keeps navigation responsive, and works identically on Capacitor targets.
1. Isolate a page into its own module
Create a folder for the page, add a module file, and declare the page component there. For example, a settings page:
src/app/settings/settings.module.ts
@NgModule({
declarations: [SettingsPage],
imports: [
IonicModule,
CommonModule,
FormsModule
]
})
export class SettingsPageModule {}
Notice the mandatory import of IonicModule; without it Ionic components render as plain HTML.
2. Configure the Angular router for lazy loading
In the root routing module (app-routing.module.ts) replace the eager route with a loadChildren string that points to the module file:
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomePageModule) },
{ path: 'settings', loadChildren: () => import('./settings/settings.module').then(m => m.SettingsPageModule) }
];
Ionic’s IonRouterOutlet works with the Angular router unchanged; navigation to /settings triggers the dynamic import and fetches the chunk.
3. Verify the split in a production build
Run a production build and inspect the output:
ionic build --prod
Open www/build (or dist if you used Angular CLI directly). You should see:
- a small
main.js(the root bundle) - a
runtime.js(Angular bootstrap) - separate files such as
settings-module.jsthat are not referenced in the initialindex.html
In Chrome DevTools → Network, navigate to the settings page. You’ll observe a request for the settings chunk after the navigation starts. The Coverage tab shows zero coverage for that chunk before navigation and non‑zero coverage after.
Trade‑off: More HTTP requests vs. smaller initial download
Lazy loading trades a single larger request for several smaller ones. On a fast connection this is usually a win because the browser can parse and execute the critical UI sooner. On a very slow or high‑latency link, the extra round‑trip to fetch a chunk can add noticeable delay before the target page appears. Mitigation strategies include:
- Preloading modules that are likely to be needed next (e.g.,
preloadStrategy: PreloadAllModulesin the router config) - Keeping the number of lazy modules reasonable; avoid creating a module for every tiny component.
Actionable closing
Start by moving one infrequently used page into its own module, add the loadChildren route, rebuild, and verify the new chunk appears in the Network tab. If the initial bundle size drops by at least 20 % and navigation feels snappier, repeat the process for other pages. Remember to always include IonicModule in each lazy module and to keep an eye on the extra requests on constrained networks.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.