Contents


Loading feature modules in Angular 4

A mixed loading strategy enhances application performance and user experience

Comments

Over the past few years, Angular has risen to popularity as a development framework for single-page web application development. Originally designed for JavaScript, Angular 4 builds on Angular 2 with support for additional languages like Dart and Typescript.

This tutorial introduces you to developing and loading feature modules in Angular. While the root module is sufficient for smaller apps, you will need to create feature modules for larger and more complex applications. You will also need to be able to load modules efficiently for optimal application performance.

Note that this tutorial is for developers familiar with basic web application development using Angular.

Feature modules in Angular

A single-page web application renders just one HTML page on startup. Along with that HTML page, the server sends an application engine to the client. The engine controls the entire application, including processing and loading HTML pages. 

An Angular application consists of the following parts:

  • Modules
  • Components
  • Templates
  • Metadata
  • Data binding
  • Directives
  • Services
  • Dependency injection

Every Angular application has at least one module, known as the root module. You bootstrap the root module to launch your Angular application. For a small application, you only need the root module and a few components. As you build out more complex, medium- to large-scale applications, you will add feature modules to your application.

Feature modules are used to organize a larger application into blocks of functionality based on your business requirements. Each module contains the features and functionality it requires, and some modules are designed to be reusable.

About the example app

This tutorial takes you through the process of creating a medium-scale web application using Angular 4. The example application presents continuously updated information in four functional areas: Markets, Sports, Weather, and Currency. In addition to developing the feature module for each area, you will consider and implement three application loading techniques.

Loading techniques

An effective loading strategy is key to a successful single-page application. For the example application, you will implement a mixed loading strategy, combining three common loading techniques:

  • Eager loading: In an eager loading scenario, all of the modules and functions are loaded on application startup. The root module is always eagerly loaded, and in some cases you will use eager loading for additional features.
  • Lazy loading: As you build out the functional areas of an application, its overall size will grow. At some point you reach a threshold where the application begins to load slowly. Lazy loading is used to reduce the initial load time for medium and large applications. In the example app, you will use lazy loading to meet the following application requirements:
    • Load application areas only on user request.
    • Faster load time for users that only visit certain (priority) areas.
    • Expand application features without increasing the size of the initial load bundle.
  • Preloading: In a preloading scenario, the main application launches all modules marked for eager loading, then almost immediately loads <ModulesDefinedAsLazyLoading> in the background. By the time the user navigates to one of these secondary modules, it will be loaded and ready to go.

For the purpose of the tutorial, assume that application users will be most interested in getting updates about financial markets and sports. You'll load those modules first, followed by the currency and weather modules.

Prerequisites

In order to follow this tutorial, you will need two tools installed on your development machine:

Enter the command ng -v to find out which version of Angular CLI and Node you are currently using. As shown below, I'm using Node 7.9.0 and Angular CLI 1.0.2.

@angular/cli: 1.0.2
node: 7.9.0
os: win32 x64

Exercise 1: Eager loading

The example application currently has two modules, AppModule and BaseModule. AppModule is the root module, and BaseModule is a feature module. BaseModule contains two functional areas: Markets and Sports. We've designated these apps for eager loading, so AppModule calls BaseModule on application startup.

Let's explore the app:

  1. Download the source code if you haven't already done it.
  2. Unzip the Angular4BaseModules source file (in Angular4TutorialSrc.zip) to an empty directory location. Mine is named …/fm.
  3. Go to the …/fm directory and enter the command npm i. This creates the node_modules directory in the …/fm folder, named …/fm/node_modules.
  4. Run the command ng serve.

You should see the app successfully running in default port 4200, with a similar message to this one:

Figure 1. The app is running port 4200
A screenshot of the server message.
A screenshot of the server message.

ng is the Angular CLI command you will use to build and serve the application code. Go to your Chrome browser and enter the URL http://localhost:4200. You should see the app running. If you click the Home icon, you will see the functional area for Markets:

Figure 2. User interface for Markets
A screenshot of the UI for markets.
A screenshot of the UI for markets.

If you click Sports, you'll see the functional area for Sports:

Figure 3. User interface for Sports
A screenshot of the UI for sports.
A screenshot of the UI for sports.

Now go to the application code in the fm/src/app directory. Here's a snapshot of the directory:

Figure 4. Application directory structure
A snapshot of the application directory in the console.
A snapshot of the application directory in the console.

In your application directory, open the file app.component.html. When a user clicks the Markets link, the app calls the /markets route. When a user clicks the Sports link, the app calls the /sports route.

Figure 5. Routes in the main app
A screenshot highlighting the application routes in the console.
A screenshot highlighting the application routes in the console.

Open the file app-routing.module.ts, shown below.

Figure 6. app-routing.module.ts
A screenshot of the open file, app-routing.module.ts, in the console.
A screenshot of the open file, app-routing.module.ts, in the console.

MarketComponent and SportsComponent are called when the /markets and /sports routes are invoked. If no route is specified, the first item in the array redirects to the /markets route.

To confirm the application function so far, go back to http://localhost:4200 in your browser. On a Windows machine, tap Fn+F12. On a Mac, enter Command->Option->i. Now you should see the Chrome developer tools GUI. View the Sources/top/ng:// section, then reload the URL. As shown in Figure 7, you should see AppModule and BaseModule automatically loaded when you restart the app.

Figure 7. Viewing Sources in Google Chrome developer tools
A screenshot of the Sources option in Chrome.
A screenshot of the Sources option in Chrome.

Exercise 2: Lazy loading

Let's assume multiple teams are developing modules for this application. Your offshore team has just delivered the Weather and Currency modules. Your task is to merge the new modules into the main app.

Unzip the Angular4LazyLoadModules file (in Angular4TutorialSrc.zip) from the application source code. Copy the weather and currency folders into your main app directory, as shown below.

Figure 8. Adding secondary modules to the main app directory
A screenshot of the main app directory with secondary modules.
A screenshot of the main app directory with secondary modules.

Your next task is to instruct Angular to implement lazy loading for the Weather and Currency modules. To add the new modules to your base application, edit your app-routing.module.ts as shown below:

Listing 1. A section of the original app-routing.module.ts
const appRoutes: Routes = [ 
  { path: '', redirectTo: '/markets', pathMatch: 'full' },
  { path: 'markets', component: MarketsComponent },
  { path: 'sports', component: SportsComponent }
];
Listing 2. A section of the updated app-routing.module.ts
const appRoutes: Routes = [ 
  { path: '', redirectTo: '/markets', pathMatch: 'full' },
  { path: 'markets', component: MarketsComponent },
  { path: 'sports', component: SportsComponent },
  { path: 'weather', loadChildren: './weather/weather.module#WeatherModule' },
  { path: 'currency', loadChildren: './currency/currency.module#CurrencyModule' } 
];

The updated code instructs Angular to load the secondary modules only upon user request. Note that the weather module's loadChildren property is set to WeatherModule's address. The address is the file location for WeatherModule (relative to the app root), followed by # separator, followed by the name of the exported module class, WeatherModule. The configuration for the Currency module is exactly the same.

When the router navigates to the updated address, it will use the loadChildren string to dynamically load WeatherModule or CurrencyModule. The first time one of the new routes is requested, the module will be lazy loaded and the application routes re-configured. The route will then be immediately available for subsequent requests.

Update the UI

Next, you will update the user interface. Find the file app.component.html in your application directory and place your cursor under the following statement:

Listing 3. A section of the original app.component.html
      <li routerLinkActive="active"> <a routerLink="/sports">Sports</a></li>

Insert the following code below the statement:

Listing 4. A section of the updated app.component.html
          <li class="dropdown"> <a href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" class="dropdown-toggle">Weather <span class="caret"></span></a>
            <ul class="dropdown-menu">
              <li routerLinkActive="active"><a [routerLink]="['/weather/yahoo']">Yahoo! Weather</a></li>
              <li routerLinkActive="active"><a [routerLink]="['/weather/facts']">Weather Facts</a></li>
              <li routerLinkActive="active"><a [routerLink]="['/weather/globalwarming']">Global Warming</a></li>
            </ul>
          </li>
          <li routerLinkActive="active"> <a routerLink="/currency">Currency</a></li>

Now the user will see and be able to click the new menus for the Weather and Sports application areas. Note that Weather has three submenus.

Save the file contents, then issue the command ng serve to run the app.

Figure 9. The app is running
A screenshot of the running app in the console.
A screenshot of the running app in the console.

Now examine the application output following the ng serve command. You should see two new lines for "chunk" files, which have been automatically added by angular-cli. These represent the modules you are lazy loading.

The app in your browser should now include the Weather and Currency menus, as shown in Figure 10.

Figure 10. Weather and Currency menus in the top-right corner
A screenshot of the new menu links in the main app UI.
A screenshot of the new menu links in the main app UI.

Under the hood

Before we move on, let's consider the details of this loading mechanism. Start by running the app in your Chrome browser. On a Windows machine, tap Fn+F12. On a Mac, enter Command->alt->i. Click the Network tab and wait for the page to load. Before you click the Weather or Currency links, look at Figure 11 (column 1) and Figure 12 (column 1) below.

Figure 11. Source code available during testing and debugging
UI view of the source files available during testing and debugging.
UI view of the source files available during testing and debugging.
Figure 12. Network-related information
UI view of network information for the app.
UI view of network information for the app.

These figures show the eager-loaded modules, AppModule and BaseModule. You can see that the Weather and Currency modules are not yet loaded.

Now try clicking the Currency menu and look at the Sources and Network tabs in Figure 11 (column 2) and Figure 12 (column 2). You should see that the Currency module (module(y.chunk.js)) has loaded. However, the Weather module has not yet loaded. Click Weather, then click one of the items under the Weather submenu. Referring to Figure 11 (column 3) and Figure 12 (column 3), you should now see that the Weather module (module(x.chunk.js)) has also loaded.

Note that the x and y chunks each have an integer value; that is how the lazy loading mechanism knows to load the modules.

Exercise 3: Preloading

Rather than waiting for the user to invoke the route for a secondary module, it's sometimes more efficient to preload these modules. In this case, after your primary modules have been eagerly loaded, the router begins preloading all remaining modules marked with the loadChildren property.

To reconfigure the app for preloading, edit your app-routing.module.ts as shown below. The following code imports the preloading modules and invokes their functionality.

Listing 5. A section of the original app-routing.module.ts
import { Routes, RouterModule } from '@angular/router';
Listing 6. A section of the updated app-routing.module.ts
import { Routes, RouterModule, PreloadAllModules } from '@angular/router';
Listing 7. A section of the original app-routing.module.ts
  imports: [RouterModule.forRoot(appRoutes)],
Listing 8. A section of the updated app-routing.module.ts
  imports: [RouterModule.forRoot(appRoutes, {preloadingStrategy: PreloadAllModules})],

Save the updated files, then run the app. Reload the app in your Chrome browser, then go to the Chrome developer tools Network and Sources tabs. The x.chunk.js and y.chunk.js files should be loaded immediately after the main application, making the secondary modules available before the user clicks these menus. See the sample application in Angular4PreLoadModules.zip for a more detailed look at preloading.

Conclusion

Load time is a key factor for application performance, which can make or break user experience for your application. In this tutorial you've been introduced to a mixed loading strategy, using the three techniques of eager loading, lazy loading, and preloading to improve application performance. Follow these rules of thumb for an effective mixed loading strategy:

  • Use eager loading for base application functions and primary modules. These are the resources that must be immediately available on application startup.
  • Use preloading for modules that most users will access, even if they are not the first or most sought application resources.
  • Use lazy loading for modules that are not highly sought.

Acknowledgments

I want to thank the wonderful IBMers John Petri, David Stanich, Mark Shade, Dean P. Cummings, and Don Turner for their review and support in writing this tutorial.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=1046341
ArticleTitle=Loading feature modules in Angular 4
publish-date=06012017