web-dev-qa-db-fra.com

Relation entre CommonJS, AMD et RequireJS?

Je suis encore très confus à propos de CommonJS, AMD et RequireJS. Même après avoir lu beaucoup.

Je sais que CommonJS (anciennement ServerJS) est un groupe permettant de définir certaines spécifications JavaScript (par exemple, des modules) lorsque la langue est utilisée en dehors du navigateur. La spécification des modules CommonJS a une implémentation telle que Node.js ou RingoJS, non?

Quelle est la relation entre CommonJS, AMD (Asynchronous Module Definition) et RequireJS? RequireJS est-il une implémentation de la définition de module CommonJS? Si oui, qu'est-ce que la DMLA alors?

802
gremo

RequireJS implémente l'API AMD(source) .

CommonJS est un moyen de définir des modules à l'aide d'un objet exports, qui définit le contenu du module. En termes simples, une implémentation CommonJS pourrait fonctionner comme ceci:

// 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"; };

En gros, CommonJS spécifie que vous devez avoir une fonction require() pour récupérer les dépendances, une variable exports pour exporter le contenu du module et un identifiant de module (qui décrit l'emplacement du module en question par rapport à ce module). ) qui est utilisé pour requérir les dépendances ( source ). CommonJS a diverses implémentations, y compris Node.js , que vous avez mentionné.

CommonJS n’a pas été conçu spécialement pour les navigateurs, il n’est donc pas adapté à l’environnement de navigateur (. Je n’ai vraiment aucune source pour cela - cela est dit partout, y compris le site RequireJS.) Apparemment, cela a quelque chose à voir avec le chargement asynchrone, etc.

D'autre part, RequireJS implémente AMD, conçu pour s'adapter à l'environnement du navigateur ( source ). Apparemment, AMD a commencé comme une retombée du format de transport CommonJS et a évolué vers sa propre API de définition de module. D'où les similitudes entre les deux. La nouvelle fonctionnalité d'AMD est la fonction define() qui permet au module de déclarer ses dépendances avant d'être chargé. Par exemple, la définition pourrait être:

define('module/id/string', ['module', 'dependency', 'array'], 
function(module, factory function) {
  return ModuleContents;  
});

Ainsi, CommonJS et AMD sont des API de définition de module JavaScript JavaScript qui ont des implémentations différentes, mais les deux proviennent des mêmes origines.

  • AMD convient mieux au navigateur, car il prend en charge le chargement asynchrone des dépendances de modules.
  • RequireJS est une implémentation de AMD, tout en même temps en essayant de garder l'esprit de CommonJS (principalement dans les identificateurs de module).

Pour vous dérouter encore plus, RequireJS, tout en étant une implémentation AMD, offre un wrapper CommonJS afin que les modules CommonJS puissent être presque directement importés pour une utilisation avec RequireJS.

define(function(require, exports, module) {
  var someModule = require('someModule'); // in the vein of node    
  exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});

J'espère que cela aide à clarifier les choses!

744
jakee

CommonJS est plus que cela - c'est un projet pour définir une API et un écosystème communs pour JavaScript. Une partie de CommonJS est la spécification Module . Node.js et RingoJS sont des exécutions JavaScript côté serveur. Oui, les deux implémentent des modules basés sur les spécifications du module CommonJS.

AMD (Définition du module asynchrone) est une autre spécification pour les modules. RequireJS est probablement l'implémentation la plus répandue d'AMD. Une différence majeure par rapport à CommonJS est que AMD spécifie que les modules sont chargés de manière asynchrone - ce qui signifie que les modules sont chargés en parallèle, par opposition à bloquer l'exécution en attendant une charge à finir.

AMD est généralement plus utilisé dans le développement JavaScript côté client (dans le navigateur) et les modules CommonJS sont généralement utilisés côté serveur. Toutefois, vous pouvez utiliser l'une ou l'autre des spécifications de module dans l'un ou l'autre environnement - par exemple, RequireJS offre instructions pour l'exécution dans Node.js et browserify est une implémentation du module CommonJS pouvant s'exécuter dans le processus. navigateur.

194
Nate

La réponse courte serait:

CommonJS et AMD sont des spécifications (ou formats) sur la façon dont les modules et leurs dépendances doivent être déclarés dans des applications javascript.

RequireJS est une bibliothèque de chargeur de script compatible AMD, curljs étant un autre exemple.

Conforme CommonJS:

Tiré de livre d'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;

Conforme à la DMLA:

// 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
    }
});

Ailleurs, le module peut être utilisé avec:

require(["package/myModule"], function(myModule) {
    myModule.foobar();
});

Quelques antécédents:

En fait, CommonJS est beaucoup plus qu'une déclaration d'API et seule une partie de celle-ci traite de cela. AMD a commencé comme une spécification préliminaire pour le format de module de la liste CommonJS, mais aucun consensus n'a été atteint et le développement du format a été déplacé vers le groupe groupe amdjs . Les arguments autour desquels le format est le mieux indiqué indiquent que CommonJS tente de couvrir un plus grand nombre de problèmes, qu’il convient mieux au développement côté serveur en raison de sa nature synchrone et que AMD convient mieux au développement côté client (navigateur), en raison de sa nature asynchrone et de la fait qu'il a ses racines dans l'implémentation de la déclaration de module de Dojo.

Sources:

184
mmutilva

Citant

AMD:

  • Une approche d'abord par navigateur
  • Opter pour un comportement asynchrone et une compatibilité ascendante simplifiée
  • Il n'a pas de concept de File I/O.
  • Il supporte les objets, les fonctions, les constructeurs, les chaînes, le JSON et de nombreux autres types de modules.

CommonJS :

  • Une approche d'abord serveur
  • En supposant un comportement synchrone
  • Couvrez un ensemble plus large de problèmes tels que les E/S, le système de fichiers, les promesses, etc.
  • Prend en charge les modules non emballés, cela peut sembler un peu plus proche des spécifications ES.next/Harmony , vous libérant ainsi du wrapper define () que AMD applique.
  • Ne supporte que les objets en tant que modules.
25
zangw

Il est tout à fait normal d’organiser le programme JavaScript de manière modulaire en plusieurs fichiers et d’appeler child-modules à partir du main js module.

La chose est que JavaScript ne fournit pas cela. Pas même aujourd'hui dans les dernières versions de navigateur de Chrome et FF.

Mais y a-t-il un mot-clé en JavaScript pour appeler un autre module JavaScript?

Cette question peut être un effondrement total du monde pour beaucoup parce que la réponse est Non .


Dans ES5 (sorti en 2009), JavaScript ne comportait aucun mot clé comme import , include , ou nécessite .

ES6 enregistre la date (publiée en 2015) en proposant le mot clé import ( https://developer.mozilla.org/en/docs/ Web/JavaScript/Référence/Instructions/import ), mais aucun navigateur ne l'implémente.

Si vous utilisez Babel 6.18.0 et transpilez uniquement avec l’option ES2015

import myDefault from "my-module";

vous obtiendrez require à nouveau.

"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

En effet, require signifie que le module sera chargé à partir de Node.js. Node.js gérera tout, de la lecture de fichier au niveau système aux fonctions d'encapsulation dans le module.

Parce que dans JavaScript, les fonctions sont les seuls wrappers pour représenter les modules.

CommonJS et AMD sont-ils confus?

CommonJS et AMD ne sont que deux techniques différentes permettant de surmonter le "défaut" de JavaScript pour charger des modules intelligemment.

13
prosti