Lazy loading views with $routeProvider

Loading

Lazy loading is a design pattern that allows you to load parts of your application only when they are needed, improving performance by reducing the initial load time. In AngularJS, you can implement lazy loading for views (or templates) by using the $routeProvider in conjunction with ngRoute to load controllers and templates dynamically.

In this guide, we’ll walk through how to implement lazy loading of views using AngularJS’s $routeProvider and ngRoute module.


1. What is Lazy Loading?

Lazy loading is the practice of delaying the loading of non-essential parts of an application until they are needed. In AngularJS, this means loading a view, controller, and its associated template only when the user navigates to that route.

The primary benefit of lazy loading is that it reduces the amount of data transferred to the client on the initial page load, leading to faster page rendering and better overall performance.


2. Setting Up Lazy Loading with $routeProvider

To enable lazy loading in AngularJS, we need to use the ngRoute module, which provides routing capabilities to load views and controllers dynamically.

Step 1: Install and Include ngRoute Module

If you’re working with AngularJS, you need to include the ngRoute module in your project. If you’re using a CDN, add the following script tag to your index.html:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-route.js"></script>

Step 2: Configure $routeProvider for Lazy Loading

The $routeProvider in AngularJS is used to define routing rules for different views and controllers. Lazy loading can be implemented by using resolve to load the necessary controller or template only when the route is accessed.

Example:

var app = angular.module('myApp', ['ngRoute']);

app.config(function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: 'home.html',
controller: 'HomeController'
})
.when('/about', {
templateUrl: 'about.html',
controller: 'AboutController'
})
.when('/contact', {
templateUrl: 'contact.html',
controller: 'ContactController'
})
.otherwise({
redirectTo: '/home'
});
});

Explanation:

  • $routeProvider.when() is used to define routes in your application. Each route has:
    • A templateUrl: The path to the HTML template for that view.
    • A controller: The controller that will manage the data for that view.
  • otherwise() is used to set the default route in case a user navigates to an undefined path.

3. Implementing Lazy Loading

To implement lazy loading, we will load the templates and controllers only when the route is accessed.

Step 3: Use resolve for Lazy Loading

The resolve property of the route configuration can be used to load the necessary controller or template asynchronously. This ensures that the required resources are fetched before the route is activated, but they are not loaded until needed.

Here’s how you can modify the previous example to lazily load the controllers and templates.

Lazy Loading Example:

var app = angular.module('myApp', ['ngRoute']);

app.config(function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: function() {
return 'home.html'; // Lazy load the template
},
controller: 'HomeController',
resolve: {
loadHomeController: function($q, $rootScope) {
var deferred = $q.defer();
require(['homeController'], function() {
deferred.resolve();
});
return deferred.promise;
}
}
})
.when('/about', {
templateUrl: function() {
return 'about.html'; // Lazy load the template
},
controller: 'AboutController',
resolve: {
loadAboutController: function($q, $rootScope) {
var deferred = $q.defer();
require(['aboutController'], function() {
deferred.resolve();
});
return deferred.promise;
}
}
})
.when('/contact', {
templateUrl: function() {
return 'contact.html'; // Lazy load the template
},
controller: 'ContactController',
resolve: {
loadContactController: function($q, $rootScope) {
var deferred = $q.defer();
require(['contactController'], function() {
deferred.resolve();
});
return deferred.promise;
}
}
})
.otherwise({
redirectTo: '/home'
});
});

Explanation:

  • templateUrl: We use a function for templateUrl to load the template only when needed.
  • resolve: The resolve property ensures that the required controller is loaded asynchronously before the route is activated. The $q.defer() creates a deferred object that is resolved once the required resources (controllers) are loaded using require().
  • require() is used to dynamically load the controller files only when the route is accessed.

4. Controller Definition and Lazy Loading

The controllers should be defined in separate files, and lazy loading of controllers can be done using require.js or any other module bundler like webpack or SystemJS.

Example: Controller File (homeController.js)

angular.module('myApp').controller('HomeController', function($scope) {
$scope.message = "Welcome to the Home page!";
});

You can load this controller asynchronously as shown in the previous example using the resolve property.


5. Performance Optimization

Lazy loading is one of the key ways to optimize the performance of a web application, especially for large AngularJS applications. Here are some additional tips:

  • Split your application: Divide your application into multiple bundles, so that you load only what you need when you need it.
  • Use code-splitting tools: Tools like webpack and SystemJS can automatically split your code into chunks and load them lazily.
  • Minimize initial payload: Only include the most essential files in the initial load (e.g., core libraries, basic UI elements).
  • Preload critical resources: For some critical views that users are likely to navigate to next, consider preloading these resources after the initial load.

6. Example: Full Application with Lazy Loading

Here’s a simple example that combines everything together:

app.js:

var app = angular.module('myApp', ['ngRoute']);

app.config(function($routeProvider) {
$routeProvider
.when('/home', {
templateUrl: 'home.html',
controller: 'HomeController',
resolve: {
loadHomeController: function($q) {
var deferred = $q.defer();
require(['homeController'], function() {
deferred.resolve();
});
return deferred.promise;
}
}
})
.when('/about', {
templateUrl: 'about.html',
controller: 'AboutController',
resolve: {
loadAboutController: function($q) {
var deferred = $q.defer();
require(['aboutController'], function() {
deferred.resolve();
});
return deferred.promise;
}
}
})
.otherwise({
redirectTo: '/home'
});
});

homeController.js:

angular.module('myApp').controller('HomeController', function($scope) {
$scope.message = "Welcome to the Home page!";
});

aboutController.js:

angular.module('myApp').controller('AboutController', function($scope) {
$scope.message = "Learn more About us!";
});

Leave a Reply

Your email address will not be published. Required fields are marked *