Lazy Loading Ionic Pages in Angular: Shrink Your Initial Bundle
Lazy loading splits an Ionic Angular app into feature modules fetched on demand, reducing initial JavaScript payload and improving perceived load time.
13 Oct 2025, 23:59 UTC

The problem: one big bundle for every screen
When you generate a new Ionic Angular application, the CLI often wires every page into the root routing module. During a production build, the bundler packs those pages into a single initial JavaScript bundle. A user on a slow mobile connection downloads code for the Settings, Profile, and Checkout screens before ever seeing the home page. That extra code delays time-to-interactive and increases data usage for features the visitor may never open.
Useful takeaway: Lazy loading defers feature modules until navigation requests them. The Ionic CLI scaffolds the module and routing files, but you still need to configure loadChildren and verify that the browser fetches a separate chunk only after the user taps a link.
How the Ionic CLI scaffolds a lazy-loaded page
Lazy loading in this context means an Angular feature module that is not imported eagerly by the root application module. Instead, the router loads it dynamically through a dynamic import. The Ionic CLI command ionic generate page creates a page component, its module, and a dedicated routing module.
Run this command in your project root. It requires ordinary write access to the src/app directory and no administrative privileges.
ionic generate page dashboard
The CLI generates src/app/dashboard/ with files such as dashboard.module.ts and dashboard-routing.module.ts. If a file with the same name already exists, the command may fail or overwrite depending on your CLI version.
Worked example: wire the Dashboard route
Open src/app/app-routing.module.ts. Replace an eager component reference with a dynamic import using loadChildren.
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
{ path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule) },
];
In your home page template, navigate with ion-router-link:
<ion-router-link routerLink="/dashboard">Open Dashboard</ion-router-link>
After a production build, the dashboard module code should not appear in the initial main.js bundle. When the user taps the link, the browser issues a separate request for the dashboard feature chunk. The exact chunk filename depends on your build configuration and Ionic/Angular versions.
Verify the split and know the trade-offs
Run the production build from the project root:
ionic build --prod --source-map
Inspect the output directory—typically www/—and compare the initial bundle size against a build where the route uses an eager component reference. Then open Chrome DevTools, open the Network tab, disable cache, navigate to the dashboard route, and confirm a new JavaScript chunk is requested only after navigation.
Lazy loading introduces two practical trade-offs. First, each feature module is an additional HTTP request. On slow networks, navigating through many lazy pages can create a request waterfall. You can mitigate this by grouping related pages into a single module or by using Angular's PreloadAllModules preloading strategy for routes that should load shortly after boot.
Second, services declared in a lazy-loaded module's providers array are scoped to that module. Each time the module loads, Angular may create a new instance. For shared services such as authentication or analytics, provide them in the root injector (providedIn: 'root') or in a shared module imported by the lazy module.
Lazy loading does not reduce the total bytes downloaded during a session; it shifts the cost from initial load to navigation time. If users immediately visit every screen, total wait time can increase rather than decrease.
Closing recommendation
Start by lazy-loading pages behind tabs, deep links, or settings screens that users visit infrequently. Keep authentication, home, and core navigation eagerly loaded if they affect first paint. After adding each lazy-loaded route, run a production build and check the Network tab to confirm a separate chunk appears only when the route is actually navigated to.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.