Seguimos profundizando en temas web, y este vez toca poner orden al descontrol de código que supone trabajar con Javascript (y TypeScript). La mejor solución es utilizar RequireJS, una librería cuyo objetivo es cargar scripts tradicionales, o módulos AMD para hacer más mantenible y reutilizable el código. Y de paso, ordenar el código, que para pequeños no hay tanto problema, pero cuando el código Javascript empieza a crecer, la cosa se complica. En la anterior entrada sobre módulos externos ya vimos un poco de RequireJS, pero ahora profundizamos más!
Qué es AMD
Lo primero es definir módulo en Javascript,que es un código que de alguna manera es “auto contenido” y que expone una interfaz pública para ser usada, además de quedar protegida del uso global. De esta forma, usando módulos es viable modularizar código Javascript para su reutilización, y para mejorar su mantenimiento.
AMD es Asyncronous Module Definition, esto es definición asíncrona de módulos. Es una API de JavaScript para definir módulos cuyas dependencias son cargadas asincrónicametente. Es útil para mejorar el tiempo de carga de los sitios web, cargando de forma asíncrona las dependencias de cada módulo antes de ejecutarlo.
Para usar módulos AMD, debe cumplir con una serie de requisitos:
- Cómo se crean los módulos
- Cómo se exportan valores
- Cómo se cargan sus dependencias
Verdaderamente deberías pensar seriamente en utilizar RequireJS si lo tuyo es trabajar con grandes aplicaciones (vaya, mi caso!). Otra ventaja es el hecho de la asincronía, porque se van cargando los módulos conforme vaya siendo necesario, haciendo que la respuesta sea más rápida.
AMD fue creado y diseñado para trabajar en el navegador (CommonJS es más específico para la parte de servidor, con NodeJS como principal valedor).
RequireJS
Es la implementación más conocida para la carga de módulos AMD. Los módulos AMD empiezan con una llamada a define, que acepta básicamente dos parámetros: un array con las dependencias del módulo y luego una función con el código del módulo:
define({ propiedad: 'valor' }); define(function modulo() { //haz lo que quieras //retorna lo que quieras }); define(function definicion_modulo() { return function modulo() { } }); define([ 'folder/dependencia' ], function definicion_modulo(dep) { return function modulo() { //usa dep } } );
Define se usa para definir módulos, que serán (o pueden ser) requeridos por otro módulos.
Es muy importante la configuración mediante require.config, y donde se detallan las características que RequireJS debe tener en cuenta, como rutas, dependencias, ….
require.config({ appDir : './src', dir : './build', baseUrl : 'js', mainConfigFile : './src/js/config.js', paths : { jQuery: '../libs/jquery/jquery.min' }, optimizeCss : 'standard', modules: [ { name: 'main' } ] })
Para entender la potencia de RequireJS sería de mucha utilidad tener todos los ficheros Javascript en un mismo subdirectorio (ver aquí).
Todo esto lo veremos detalladamente en la plantilla que utilizo para trabajar con TypeScript, RequireJS, jQuery y Bootstrap.
Por último, les dejo este artículo donde describen muy bien RequireJS y AMD.
Happy coding!