Post on 08-Sep-2014
description
Lazy Loading Techniques
nirkaufman@gmail.com
Introduction
Nir Kaufmannirkaufman@gmail.com
AngularJS infrastructures - lazy loading techniques:
1. Introducing the lazy loading challenges with AngularJS
2. Review a working demo project
nirkaufman@gmail.com
AngularJS encourage us to break our code into smaller pieces.
services
directives
controllers
filters constants
Modules
overview
nirkaufman@gmail.com
Separating your code into multiple files considered a best practice when building large apps with angular.
❖ js/■ controllers.js■ services.js■ directives.js■ filters.js
❖ partials/■ partial1.html■ partial2.html
Angular seed project:
angular.module('myApp.controllers', []).
controller('MyCtrl1', function() {
})
.controller('MyCtrl2', function() {
});
overview
nirkaufman@gmail.com
We can define our modules as dependencies:
angular.module('myApp',['ngRoute',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers',
’ngRoute’,
’ngResource’,
’ui.bootstrap’,
]).
overview
nirkaufman@gmail.com
but we must load all of our resources ahead:
<script src="lib/angular.js"></script>
<script src="lib/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
………………..
<script src="lib/angular-resource.js"></script>
<script src="lib/angular-bootstrap.js"></script>
<script src="lib/underscore.js"></script>
overview
nirkaufman@gmail.com
All components must register against our module on bootstrap. otherwise we can't use them.
Error: Argument ‘myController’ is not a function, got undefined
Lazy Loading Angular componentsregister
overview
nirkaufman@gmail.com
We need to answer those 3 questions in order to solve this challenge:
● How to lazy load scripts async ?
● How to register our components against
our module after bootstrap?
● When & where the actual loading occurs?
solution
nirkaufman@gmail.com
RequireJS provides a clean way to load and manage dependencies for our applications.
<script data-main="main" src="require.js"></script>
define(function () {
// module code} )
require([‘module’], function (module) {
// use this module} )
http://requirejs.org/
loading
nirkaufman@gmail.com
Components register against the module in the config phase using providers.For instance, we can register our controller manually using the ‘$controllerProvider’:
angular.module('moduleName', [])
.config(function($controllerProvider) {
$controllerProvider.register('Ctrl', function () {// controller code
})});
register
nirkaufman@gmail.com
All components can be registered with their matching provider methods:
// services can register with $provide
$provide.service() $provide.factory(),$provide.value(),$provide.constant(),
// other components use specific providers
$controllerProvider.resgister()$animateProvider.resgister()$filterProvider.resgister()$compileProvider.directive()
register
nirkaufman@gmail.com
we need to hold a reference to this provider in order to use it later in our code:
var app = angular.module('moduleName', [])
.config(function($controllerProvider) {
app.loadController = $controllerProvider.register;
})
});
app.loadController(‘someCtrl’, function ($scope) {})
register
nirkaufman@gmail.com
Where in the application should the actual loading take place?
● when routing to a view - $routeProvider
● when loading content - <ng-include>
● in response to event - like click or hover
when to load
nirkaufman@gmail.com
The route object contain a ‘resolve’ property that can accept a map of promises and wait for them to resolve before performing the route
angular.module('moduleName', [])
.config(function($routeProvider) {
$routeProvider.when('/', {templateUrl: 'view.html',controller : 'controller.js',resolve : // promise
})})
});
routing
nirkaufman@gmail.com
If every view managed by a controller we can reflect that in our project structure by packing them together & come up with naming conventions:
❖ views
➢ view-name■ view-name.html■ view-name.js
➢ another-view■ another-view-name.html■ another-view-name.js
.controller(‘viewNameCtrl’, ….
routing
nirkaufman@gmail.com
We can load our dependencies as a reaction to an event.we can be creative and load our resources depending on the user behaviour:
events
● load only when a user start to fill a form● load by mouse position ● load when a response comming back from
the server
nirkaufman@gmail.com
What about module loading? ocLazyLoad is probably the best solution for lazy loading angular modules (for now):
● Dependencies are automatically loaded
● Debugger like (no eval code)
● The ability to mix normal boot and load on demand
● Load via the service or the directive
● Use your own async loader (requireJS, script.js ...)
https://github.com/ocombe/ocLazyLoad
modules
nirkaufman@gmail.com
Lazy loading in Angular can be achived today with minimum effort.to keep our loading infrastructure flexible:
1. keep the loading logic in separated services this will make our life easier when this feature will be officially supported
2. use naming conventions this way developers can integrate more easily when moving between projects
summary
nirkaufman@gmail.com
Thank You!Demo project source code:
summary
https://github.com/nirkaufman/lazyLoadingDemo