Requirejs carga selectiva de módulos javascript

Hola!

Hoy os traigo un tema muy interesante, con el que llevo trabajando ya varios meses y que me parece oportuno hablar..     😉

Un pelín de teoría: AMD son las siglas para el término Asynchronous Module Definition, una aproximación, una API, un mecanismo para definir módulos y sus dependencias, con la característica de que estos módulos y dependencias son cargados asíncronamente! (léase para más información al respecto esto).

RequireJS es una librería JS  que implementa AMD y nos ayudará a cargar módulos de javascripts en nuestros desarrollos/proyectos de forma asíncrona a la carga de nuestra web. Nos facilitará la carga selectiva de las diferentes funcionalidades de nuestras aplicaciones web.

Esta manera de enfocar, mediante módulos javascript (incluyendo como módulo cualquier librería de terceros que necesite el proyecto), nos proporciona unas ventajas interesantes:

  • división de toda la funcionalidad de cliente en diferentes ficheros,
  • mayor mantenibilidad del código (mayor organización),
  • rapidez en la carga inicial de la aplicación (ya que podremos no cargar toda la funcionalidad desde el comienzo)

El uso es de esta librería es muy simple.

  1. En primer lugar importemos en nuestro proyecto html la librería:
    <script data-main="main" src="scripts/require.js"></script>
  2. Cuando cargamos require.js suceden dos cosas en nuestro proyecto: primero se crea un objeto llamado «require» que será el que controle la carga y configuración de los diferentes módulos para el sistema.
  3. El data-main de la línea anterior lo que hará será cargar el punto de entrada de toda las dependencias que nuestra app requiera… es decir básicamente cargará el main.js de nuestra carpeta script. Y este fichero será de la forma siguiente (aquí es donde entra en juego requireJS).
    require(["mifunc1"], function(mifunc1) {
        //Esta función será llamada cuando mifunc.js sea cargada.
        //Si la llamada mifunc.js llama a su vez a define(), entonces esta función no se llamará hasta que dicho define() 
        //cargue todas sus dependencias y mifunc1 no contenga todo el valor del módulo contenido en mifunc1.
        var c = mifunc1.suma(1,2);
        console.debug(c);
    });
  4. A partir de aquí todo nuestro javascript debe ser escrito orientado a «AMD». Esto significa que la funcionalidad de nuestra aplicación la debemos modularizar. Y yo aconsejo que cada módulo corresponda a un fichero físico js diferente. Nuestra funcionalidad se escribirá de la siguiente forma:
    define(
        function() {
    	    var suma = function(a, b){
    	    	return (a+b);
    	    }
    	    var resta = function(a, b){
    	    	return (a-b);
    	    }
    	    return {
    	        suma: suma,
    	        resta: resta
    	    }
        }
    );
  5. Si el código anterior lo guardamos en un fichero llamado mifunc1.js y cargamos un index.html que llame al main anterior veremos en nuestra consola js un 3… resultado de la suma de uno y dos.

Y esto es prácticamente todo… a partir de aquí podemos hacer que cuando suceda determinado evento en nuestra página llamemos a una función de nuestro main.js que tenga otro require y cargue el módulo asociado a ese evento y continúe la ejecución del evento a través de dicho módulo…

Por ejemplo, si queremos que al hacer click en un botón aparezca un modal con un aviso, podemos crear esa funcionalidad y crearla dentro de un módulo llamada modal.js. En nuestro main.js creamos una función que la llamaremos cuando se tenga que disparar ese modal y por ejemplo un parámetro que sea el texto de dicho modal:

function muestraModal(texto){
    require('modal', function(modal){
        modal.mostrarModalInfo(texto);
    });
}

Y en nuestro modal.js algo como…

define(['jquery', 'mas-dependencias-del-modal'], 
    function($, mas-dependencias) {
	    var modal = function(texto){
	    	//la lógica para mostrar un modal con el texto pasado por argumento...
	    }
	    return {
	        modal: modal
	    }
    }
);

¿qué os parece? ¿os parece útil?

Dejadme en comentarios si queréis que amplíe más esta información y hago un tutorial más extenso

Un abrazo!

6 comentarios

  1. Interesante artículo y bien explicado. Actualmente estoy mirando como crear una nueva ruta angularjs de forma dinámica asociada a un botón que cuando haga click en el mismo cargue un módulo, entendemos por módulo: template html + js con el controlador del mismo template.

    Presupongo que requireJS es el camino, pero aún no se como plantearlo.

    Gracias.

    1. Hola Miguel!

      Gracias por pasarte!

      Para lo que comentas, en angularjs existe la directiva ng-include ¿le has hechado un vistazo?

      Con requirejs se puede hacer lo que comentas, sin embargo, yo no he probado la compatibilidad de ambas librerías…

      Muchas gracias!

  2. Hola, me parece muy interesante RequireJS me gustaría mucho un tutorial para el uso de carga de ficheros externos HTML (templates externos) para así poder cargar todo de forma asincronica.

    1. Hola Harry!

      Creo que para cargar html externo (habría que ver el caso antes), lo mejor sería usar directamente AngularJS (o Polymer: WebComponents) y hacer la app con esta arquitectura.

      Gracias por pasarte!

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.