¿Relación entre CommonJS, AMD y RequireJS?
Todavía estoy muy confundido acerca de CommonJS, AMD y RequireJS , incluso después de leer mucho.
Sé que CommonJS (anteriormente ServerJS ) es un grupo para definir algunas especificaciones de JavaScript (es decir, módulos) cuando el lenguaje se usa fuera del navegador. La especificación de los módulos CommonJS tiene alguna implementación como Node.js o RingoJS , ¿verdad?
¿Cuál es la relación entre CommonJS , Definición de módulo asincrónico (AMD) y RequireJS ?
¿Es RequireJS una implementación de la definición del módulo CommonJS ? En caso afirmativo, ¿qué es AMD entonces?
RequireJS implementa la API de AMD (fuente) .
CommonJS es una forma de definir módulos con la ayuda de un exports
objeto, que define el contenido del módulo. En pocas palabras, una implementación de CommonJS podría funcionar así:
// someModule.js
exports.doSomething = function() { return "foo"; };
//otherModule.js
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
Básicamente, CommonJS especifica que necesita tener una require()
función para recuperar dependencias, una variable para exportar el contenido del módulo y un identificador de módulo (que describe la ubicación del módulo en cuestión en relación con este módulo) que se utiliza para requerir las dependencias ( fuente)exports
. ). CommonJS tiene varias implementaciones, incluido Node.js , que mencionaste.
CommonJS no fue diseñado particularmente teniendo en cuenta los navegadores, por lo que no encaja muy bien en el entorno del navegador (*Realmente no tengo una fuente para esto; simplemente lo dice en todas partes, incluido el sitio RequireJS.* ) Aparentemente, esto tiene algo que ver con la carga asincrónica, etc.
Por otro lado, RequireJS implementa AMD, que está diseñado para adaptarse al entorno del navegador ( fuente ). Aparentemente, AMD comenzó como un derivado del formato CommonJS Transport y evolucionó hasta convertirse en su propia API de definición de módulo. De ahí las similitudes entre ambos. La nueva característica de AMD es la define()
función que permite al módulo declarar sus dependencias antes de ser cargado. Por ejemplo, la definición podría ser:
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
return ModuleContents;
});
Entonces, CommonJS y AMD son API de definición de módulos JavaScript que tienen implementaciones diferentes, pero ambas provienen del mismo origen.
- AMD es más adecuado para el navegador porque admite la carga asíncrona de dependencias de módulos.
- RequireJS es una implementación de AMD , al mismo tiempo que intenta mantener el espíritu de CommonJS (principalmente en los identificadores de módulos).
Para confundirlo aún más, RequireJS, si bien es una implementación de AMD, ofrece un contenedor CommonJS para que los módulos CommonJS se puedan importar casi directamente para usarlos con RequireJS.
define(function(require, exports, module) {
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});
CommonJS es más que eso: es un proyecto para definir una API y un ecosistema comunes para JavaScript. Una parte de CommonJS es la especificación del módulo . Node.js y RingoJS son tiempos de ejecución de JavaScript del lado del servidor y sí, ambos implementan módulos basados en la especificación del módulo CommonJS.
AMD (Definición de módulo asíncrono) es otra especificación para módulos. RequireJS es probablemente la implementación más popular de AMD. Una diferencia importante con CommonJS es que AMD especifica que los módulos se cargan de forma asincrónica , lo que significa que los módulos se cargan en paralelo, en lugar de bloquear la ejecución esperando a que finalice la carga.
AMD generalmente se usa más en el desarrollo de JavaScript del lado del cliente (en el navegador) debido a esto, y los módulos CommonJS generalmente se usan en el lado del servidor. Sin embargo, puede usar cualquiera de las especificaciones del módulo en cualquier entorno; por ejemplo, RequireJS ofrece instrucciones para ejecutar en Node.js y browserify es una implementación del módulo CommonJS que se puede ejecutar en el navegador.
La respuesta corta sería:
CommonJS y AMD son especificaciones (o formatos) sobre cómo se deben declarar los módulos y sus dependencias en aplicaciones javascript.
RequireJS es una biblioteca de carga de scripts compatible con AMD, siendo curljs otro ejemplo.
Compatible con CommonJS:
Tomado del libro de Addy Osmani .
// package/lib is a dependency we require
var lib = require( "package/lib" );
// behavior for our module
function foo(){
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
exports.foobar = foo;
Compatible con AMD:
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
En otros lugares, el módulo se puede utilizar con:
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
Algunos antecedentes:
En realidad, CommonJS es mucho más que una declaración API y solo una parte se ocupa de eso. AMD comenzó como un borrador de especificación para el formato del módulo en la lista CommonJS, pero no se alcanzó un consenso total y el desarrollo posterior del formato se trasladó al grupo amdjs . Los argumentos sobre qué formato es mejor afirman que CommonJS intenta cubrir un conjunto más amplio de preocupaciones y que es más adecuado para el desarrollo del lado del servidor dada su naturaleza sincrónica, y que AMD es más adecuado para el desarrollo del lado del cliente (navegador) dada su naturaleza asincrónica y la hecho de que tiene sus raíces en la implementación de la declaración del módulo de Dojo.
Fuentes:
- RequireJS: ¿Por qué AMD?
- Addy Osmani - Aprendizaje de patrones de diseño de JavaScript - Patrones de diseño de JavaScript modulares modernos