Introduction Angular Loadable (ngx-loadable ~ 2.2kB)
A simpler way to lazy load non routable angular modules!
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 wrote 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 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?
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-loadable
element.
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”.