Ionic and Lazy Loading Pt 1
Hi there folks! When we were working on release 3.0.0, our main goal was to add lazy loading to the framework and make it as easy as possible. While we are still labeling lazy loading as a beta/non-default setting, many developers who are adding lazy loading to their apps are asking question regarding best practices and examples. I thought this warranted a post on the subject to dive how to set up an app for lazy loading.
Note: the approach to lazy loading here is for version 3.0.0 and up. Since lazy loading is still beta/experimental, the details of this may change in the future.
The main module
Lazy loading sounds like a complicated process, but actually is very straight forward. Conceptually, we’re taking one segment of code, a chunk, and loading it on demand as the app requests it. This is a very framework agnostic take on things, and the finer details here come in the form of NgModules
for Ionic apps. NgModules
are the way we can organize our app’s pages, and separate them out into different chunks.
Let’s take this one piece at a time and use a blank starter app to get our bearings.
ionic start lazyLoadingBlank blank
cd lazyLoadingBlank
Now if we open our src/app/app.module.ts
file, we can inspect the default NgModule
:
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
@NgModule({
declarations: [MyApp, HomePage],
imports: [ ... ],
bootstrap: [IonicApp],
entryComponents: [MyApp, HomePage],
providers: [ ... ]
})
export class AppModule {}
We can see here that we’re importing the MyApp
component and the HomePage
component. Now we want to remove the HomePage
component from this module, and load it only when we need it. So we can remove the HomePage
reference in declarations
and entryComponents
, as well as the import statement.
So how can we have HomePage
lazily loaded? We can provide it with it’s own NgModule
which will encapsulate everything that the component needs to function.
Let’s create a new file src/pages/home/home.module.ts
and scaffold it out.
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { HomePage } from './home';
@NgModule({
declarations: [HomePage],
imports: [IonicPageModule.forChild(HomePage)],
})
export class HomePageModule { }
There’s not a lot going on here, but IonicPageModule
is probably something new. Similar to IonicModule
in the main app.module.ts
, this tells Ionic what component it should load or provide for this chunk. We can export an empty class and wrap up our module. The last part we need to do now is decorate our HomePage
component.
In src/pages/home/home.ts
let’s add the @IonicPage
decorator.
<br />import { Component } from '@angular/core';
import { IonicPage } from 'ionic-angular';
@IonicPage()
@Component(... )
export class HomePage { ... }
This IonicPage
decorator is how Ionic generates the proper mappings and URL slugs for your app at build time. IonicPage
has a few options you can pass to it, but for now we won’t worry about them. All we need to know is that when we want to navigate or reference this component in our code, we can pass the string HomePage
instead of a reference to the class directly.
Speaking of, we have the last bit of cleaning up to do. In src/app/app.component.ts
we have an import statement and reference to HomePage
. Let’s remove the import statement, and then for rootPage
, we can set it to 'HomePage'
.
rootPage:any = 'HomePage';
Congratulations! You have now gone through the process of lazy loading the Home page!
Ok, so at a basic level, there’s not a whole lot going on here, it’s mostly centered around organizing your code, and creating NgModule
s for the pages you want lazy loaded, and adding the @IonicPage
decorator to the component.
I’ve put together some examples on how this can work for something a bit more complicated, like a Tabs based app.
Cool, so why bother?
Now that we’re lazy loading HomePage
, what can we expect to see? If we start to inspect our app, we can see what we’re sending over the network.
If we look at what we’re sending over the network, we have our main.js
bundle (which includes our root app component, angular, and our initial dependencies) and then 0.main.js
, which is just our HomePage
. Our main chunk is now much smaller, and can be loaded much faster. Same goes for our Home chunk, the code being sent over is only what that chunk requires, so it loads much faster.
Now it’s important to note, that this does not mean our apps final bundle size is smaller, but we’re distributing the bytes and only loading what is needed.
Now our small app may seem a bit contrived, but as apps start to grow, the ability to lazy load additional components becomes much more important. Consider apps with 50+ different pages and many more UI components. Loading these all up front is very resource expensive. Instead, if you can only load 2-4 different components up front and lazy load the rest, users will have a much better experience.
What’s next
We’ve really only scratched the lazy loading surface and concepts behind it. In a follow-up post, we’ll go over how we can structure our app so we can better support lazy loading of: Component, Directives, and Pipes.