Introduction Angular Loadable (ngx-loadable ~ 2.2kB)

A simpler way to lazy load non routable angular modules!

Working example using slow network to demonstrate ngx-loadable (demo)

Demo | Source Code

NOTE: I am a Software Architect who has a passion for Angular, React and AWS. Currently I am working on a React and AWS project, but Angular Community makes me feel at home ❤ and so because of that, I am actively writing a book, “Angular Projects”

One thing that always used to make me a bit uncomfortable when I worked on Angular Projects (pre v6) after I had worked on React for a while was because I could only lazy load routable Angular Modules. In React, you could lazy load any component using react-loadable or even React.lazy.

I got excited when I read Netanel Basal article on lazy loading non routable Angular Modules last week (even though the feature was available from Angular v6). But I felt it has a lot of steps for implementing lazy loading, so I decided to create a library ngx-loadable which can lazy load non routable Angular modules, manage different stages of loading and also allow you to preload the modules when required with a simpler API.

ngx-loadable

The library logo represents faster application like speed of wind

The Problem:

Angular provides an easy way for adding route based lazy loading modules. But in most of the projects, each route tends to have a lot of different components. It could be because of lots of modals, tabs, and components that appear based on user interaction in a single route.

One way to solve this is by lazy loading javascript for those components that appear on user interaction on the page.

This can help the routes to load faster. Suppose your page has lots of content, and you only want to load the components or libraries when the content appears (on user scroll). Why would we want to download all the content at the same time as the content on the top?

Route vs. component centric code splitting (Image: react-loadable)

Angular provides a solution for that, but its not as simple as lazy loading route based Angular Modules. Current solution for Lazy Loading non-routable Angular Modules has a lot of steps to follow as described in the article pointed above.

The Solution:

The ngx-loadable wraps the complex implementation for lazy loading non routable modules in a simple API. It provides a component ngx-loadable and a service LoadableService to lazy load modules. A component can be used to control the loading of one module and to display different states, i.e. loading, error, timedOut and loaded.

Step 1: First install ngx-loadable using npm/yarn, and then include the LoadableModule in your AppModule.

Step 2: Add a module with a component bootstrapped. So lets imagine we have a module called login-modal. You would create it using Angular CLI with the following commands

> ng g m login-modal
> ng g c login-modal -m login-modal

Note: The module and component name should be the same and should be generated in the default directory. If you want to change it, you need to pass configuration to the LoadableModule, which we will look at later in the article.

Don’t forget to add the component in the bootstrap

Step 3:

Now just add the path of the LoginModalModule to angular.json to lazyModules array. This will let Angular CLI know that it has to create a lazy loaded script for this path. This will hopefully be automated by a flag using Angular CLI in future.

Step 4: Use the Component ngx-loadable

<button (click)="show = true" (mouseenter)="loginModalModule.preload()">
Preload on mouseenter and show on click
</button>
<ngx-loadable
#loginModalModule
[module]="'login-modal'"
[show]="show"
[timeout]="1000"
>
<div loading>Loading...</div>
<div error>Error</div>
<div timedOut>
TimedOut!
<button (click)="loginModalModule.reload()">
Reload
</button>
</div>
</ngx-loadable>

In this example, when the mouse is hovered on the button, the LoginModal Module is preloaded, and upon the click of the button, if the module is still downloading, then the loading slot is used to show the loading message, and then the LoginModalComponent loads in the ngx-loadableelement.

OR use preload/preloadAll method from the LoadableService to load the Module/Modules

import { LoadableService } from 'ngx-loadable';
...
class YourComponent {
contructor(private loadableService: LoadableService) { }
    load() {
this.loadableService.preload('lazy')
.then(() => console.log('loaded'))
.catch((error) => console.error(error));
}
}
}

ngx-loadable works out of the box for simple Angular applications which has all the modules in the src/app folder. You can configure ngx-loadable to use custom paths, by passing configuration to the LoadableModule

@NgModule({
imports:[
BrowserModule,
LoadableModule.forRoot({
appDir: 'src/app/lazy-loaded-modules/',
fileMapping: {
widget: 'src/app/custom/widget.module#SomeModule'
}
})
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

Tips:

Use ngx-perimeter to preload based on proximity of mouse near an element, or use ngxInViewport to load and show the content if the content is in viewport.

Conclusion:

Without worrying about different steps to implement lazy loading of non routable modules, ngx-loadable provides a simple component to manage the lazy loading.

Let us know about any additional features that you want ngx-loadable to provide related to lazy loading in the github repo.


👋 Hi! I’m Zama Khan Mohammed. I work at Tekzenit as a Software Architect — Web Technolgies. I’m actively involved in working on Projects using Angular, React and Serverless Technologies along with writing a book “Angular Projects”.