Late registering
&
Lazy loading
Gonzalo Ruiz de Villa Suárez
@gruizdevilla
@gruizdevilla
Proyecto de ejemplo
Los fuentes los puedes encontrar en:
https://github.com/gonzaloruizdevilla/angularlazyload
Para arrancar el proyecto:
$ npm install
$ bower install
$ npm start
y entra en http://localhost:3000/
De base,
AngularJS no permite
el registro de artefactos
después de arrancar la aplicación.
Sin embargo,
se pueden acceder
a las piezas de registro
al arrancar la aplicación.
Al exponerlas, de forma artificial, podemos utilizarlas más adelante para registrar más artefactos.
Exponiendo métodos para registro posterior
module.config(
function (
$controllerProvider,
$compileProvider,
$filterProvider,
$provide
) {
module.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
}
);
Para registrar un nuevo servicio una vez arrancada la aplicación:
module.lazy.factory('MySrv', function () {
//factory body
});
Los tests unitarios se pueden complicar. Para evitarlo:
(module.lazy || module).factory('MySrv', function () {
//factory body
});
Al probar unitariamente se registran antes de arrancar.
O mejor, si hacemos esto:
module.config(
function (
$controllerProvider,
$compileProvider,
$filterProvider,
$provide
) {
module.controller = $controllerProvider.register;
module.directive = $compileProvider.directive;
module.filter = $filterProvider.register;
module.factory = $provide.factory;
module.service = $provide.service;
}
);
En la etapa de configuración,
reemplazamos métodos inútiles por los que nos permiten registrar.
Limitaciones
- No hay soporte oficial para estas técnicas.
- La fase de configuración ya terminó, por lo tanto:
- No se pueden configurar los nuevos recursos. Por lo tanto no tiene sentido registrar con provider, por ejemplo.
- No se pueden decorar los nuevos recursos
- No se pueden agregar nuevos módulos
En mi experiencia, estas limitaciones no son importantes para los recursos que tengo que cargar a posteriori.
Lazy load
Es importante encontrar la convención adecuada para tu proyecto: minimiza la configuración de lazy load.
La estrategia: apoyarse en las configuraciones de las rutas. Agrega en '
resolve
' una función que devuelve una promesa que se resuelva al cargar las dependencias.Script.js
Para el ejemplo, uso script.js, una superligera (1.5kb) librería de carga asíncrona de scripts:
bower install script.js --save
https://github.com/ded/script.js
Preparar la configuración de una ruta:
function resolveDependencies(config, dependencies) {
config.resolve = {
dependencies: function ($q, $rootScope) {
var deferred = $q.defer();
$script(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}
};
}
Usando RequireJS
Los principios son los mismos,
pero ligeramente más complicado
pero ligeramente más complicado
por la idiosincrasia de AMD:
- Pasa la referencia al módulo de AngularJS
mediante los mecanismos de RequireJS - El arranque de la aplicación (bootstrap)
de AngularJS se debe hacer de forma manual.
RequireJS o no RequireJS
- RequireJS es mucho más potente,
pero añade complejidad en: - Configuración: dependencias definidas dos veces
en cada fichero, en 'define' y al registrar el recurso
en AngularJS. Sin RequireJS, también hay
esa duplicidad, pero se puede eliminar con
convenciones en nomenclatura. - Testing más complicado con RequireJS.
Con la primera técnica librería, el testing
es el habitual de AngularJS.
¡Gracias!
Late registering and lazy load in AngularJS
By Gonzalo Ruiz de Villa
Late registering and lazy load in AngularJS
Late registering and lazy load in AngularJS
- 4,254