Sử dụng Lazy loading directives trong AngularJS

Giới thiệu

Với 1 trang web thông thường,khi người dùng truy cập vào lần đầu tiên thì sẽ không tránh khỏi việc load tất cả các file JS đc dùng.Việc này có thể ảnh hưởng khá nhiều tới performence cho hệ thống.Bài viết này sẽ giới thiệu với các bạn 1 cách để tránh việc này, đó là chỉ load các phần tối thiểu của hệ thống và sau đó sẽ load từng phần mà trang web cần dùng vào (hay còn gọi là lazy loading).

Sử dụng Lazy loading với directives

Đầu tiên bạn cần phải tham chiếu đến $compileProvider. Provider đã có sẵn trong hệ thống và sẽ giúp biên dịch các directive

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

app.config(['$routeProvider', '$compileProvider', function($routeProvider, $compileProvider) {
    $routeProvider.when('/', {
        templateUrl: 'views/Home.html',
        controller: 'HomeController'
    });

    app.compileProvider = $compileProvider;
}]);

Giờ ta có thể viết 1 service để thực hiện việc load và biên dịch các directives để sẵn sàng sử dụng:

app.service('LazyDirectiveLoader', ['$rootScope', '$q', '$compile', function($rootScope, $q, $compile) {

    var _directivesFileMap = {
        'SexyDirective': 'scripts/directives/sexy-directive.js'
    };

    var _load = function(directiveName) {
        // make sure the directive exists in the dictionary
        if (_directivesFileMap.hasOwnProperty(directiveName)) {
            console.log('Error: doesnt recognize directive : ' + directiveName);
            return;
        }

        var deferred = $q.defer();
        var directiveFile = _directivesFileMap[directiveName];

        // download the javascript file
        var script = document.createElement('script');
        script.src = directiveFile;
        script.onload = function() {
            $rootScope.$apply(deferred.resolve);
        };
        document.getElementsByTagName('head')[0].appendChild(script);

        return deferred.promise;
    };

    return {
        load: _load
    };

}]);

Trong ví dụ trên, tôi có khai báo services với tên LazyDirectiveLoader và function load(directiveName) thực hiện việc load các file js với tham số là tên của directives.

Giờ ta có thể gọi directives để sử dụng bằng cách :

app.controller('CoolController', ['LazyDirectiveLoader', function(LazyDirectiveLoader) {

    LazyDirectiveLoader.load('SexyDirective').then(function() {
        // do somethings()
    });

}]);

Chú ý là directives cần được sử dụng thông qua việc gọi '$compileProvider',đó là lý do tôi đã khai báo biến $compileProvider ngay trong lúc khởi tạo app :

app.compileProvider.directive('SexyDirective', function() {
    return {
        restrict: 'E',
        template: '<div class=\"sexy-directive\"></div>',
        link: function(scope, element, attrs) {

        }
    };
});

Bằng các bước thực hiện ở trên, giờ bạn có thể tùy biến khai báo và sử dụng các directives bất cứ khi nào bạn cần mà ko cần phải load tất cả các đối tượng vào app ngay từ lần đầu load ứng dụng.