Связь между CommonJS, AMD и RequireJS?

Я все еще очень смущен про CommonJS, AMD и RequireJS. Даже после прочтения много.

Я знаю, что CommonJS (ранее ServerJS) - это группа для определения некоторых спецификаций JavaScript (например, модулей), когда язык используется вне браузера. Спецификация модулей CommonJS имеет некоторую реализацию, например Node.js или RingoJS, правильно?

Какова связь между CommonJS, асинхронным определением модулей (AMD) и RequireJS? Является ли RequireJS реализацией определения модуля CommonJS? Если да, то что AMD тогда?

Ответ 1

RequireJS реализует API AMD (источник).

CommonJS - это способ определения модулей с помощью объекта exports, который определяет содержимое модуля. Проще говоря, реализация CommonJS может работать следующим образом:

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

В основном, CommonJS указывает, что вам нужно иметь функцию require() для извлечения зависимостей, переменную exports для экспорта содержимого модуля и идентификатор модуля (который описывает расположение соответствующего модуля относительно этого модуля) для использования зависимостей (source). CommonJS имеет различные реализации, в том числе Node.js, которые вы упомянули.

CommonJS не был специально разработан с учетом браузеров, поэтому он не подходит в среде браузера очень хорошо (у меня действительно нет источника для этого - он просто так везде говорит, включая сайт RequireJS.) По-видимому, это как-то связано с асинхронной загрузкой и т.д.

С другой стороны, RequireJS реализует AMD, которая разработана в соответствии с средой браузера (source). По-видимому, AMD начала как продолжение формата CommonJS Transport и превратилась в собственный API определения модуля. Отсюда и сходство между ними. Новая функция в AMD - это функция define(), которая позволяет модулю объявлять свои зависимости перед загрузкой. Например, определение может быть:

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

Итак, CommonJS и AMD - это JavaScript API-интерфейсы определения модулей, которые имеют разные реализации, но оба они происходят из одного и того же происхождения.

  • AMD больше подходит для браузера, поскольку поддерживает асинхронную загрузку зависимостей модулей.
  • RequireJS - это реализация AMD, в то же время пытаясь сохранить дух CommonJS (главным образом, в идентификаторах модуля).

Чтобы еще больше запутать вас, RequireJS, будучи реализацией AMD, предлагает обертку CommonJS, поэтому модули CommonJS могут быть непосредственно импортированы для использования с RequireJS.

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

Надеюсь, это поможет прояснить ситуацию!

Ответ 2

CommonJS - это нечто большее - это проект для определения общего API и экосистемы для JavaScript. Одна часть CommonJS - это Module. Node.js и RingoJS - это время выполнения JavaScript на стороне сервера, и да, оба из них реализуют модули на основе спецификации модуля CommonJS.

AMD (определение асинхронного модуля) - еще одна спецификация для модулей. RequireJS, вероятно, является самой популярной версией AMD. Одно существенное отличие от CommonJS заключается в том, что AMD указывает, что модули загружаются асинхронно - это означает, что модули загружаются параллельно, а не блокируют выполнение, ожидая завершения загрузки.

AMD, как правило, больше используется в клиентской (в браузере) JavaScript-разработке из-за этого, а модули CommonJS обычно используются на стороне сервера. Однако вы можете использовать любую спецификацию модуля в любой среде - например, RequireJS предлагает направления для работы в Node.js и browserify - это реализация модуля CommonJS, которая может запускаться в браузере.

Ответ 3

Короткий ответ:

CommonJS и AMD являются спецификациями (или форматами) о том, как модули и их зависимости должны быть объявлены в приложениях javascript.

RequireJS - это библиотека загрузчика script, совместимая с AMD, curljs является еще одним примером.

Совместимость с CommonJS:

Взято из Addy Osmani book.

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

Совместимость с 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
    }
});

В другом месте модуль можно использовать с:

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

Некоторая предыстория:

Собственно, CommonJS - это гораздо больше, чем декларация API, и только часть этого имеет дело с этим. AMD началась как проект спецификации формата модуля в списке CommonJS, но не был достигнут полный консенсус и дальнейшая разработка формата перенесена в amdjs group. Аргументы вокруг какого формата лучше утверждают, что CommonJS пытается охватить более широкий круг проблем и что он лучше подходит для развития на стороне сервера с учетом его синхронного характера и что AMD лучше подходит для развития клиентской стороны (браузера), учитывая его асинхронный характер и факт, что он имеет свои корни в реализации декларации модуля Dojo.

Источники:

Ответ 4

Цитата

AMD

  • Один подход, основанный на браузерах
  • Выбор асинхронного поведения и упрощенная обратная совместимость
  • В нем нет понятия ввода/вывода файлов.
  • Он поддерживает объекты, функции, конструкторы, строки, JSON и многие другие типы модулей.

CommonJS

  • Один подход к серверу
  • Предполагая синхронное поведение
  • Покройте более широкий набор проблем, таких как ввод-вывод, файловая система, Promises и многое другое.
  • Поддерживает развернутые модули, он может чувствовать себя немного ближе к спецификациям ES.next/Harmony, освобождая вас от обертки define(), которая AMD обеспечивает,
  • Поддерживать объекты только как модули.

Ответ 5

Вполне нормально организовать модульную программу JavaScript в несколько файлов и вызвать child-modules из main js module.

Дело в том, что JavaScript не предоставляет этого. Даже сегодня в последних версиях браузера Chrome и FF.

Но есть ли в JavaScript ключевое слово для вызова другого модуля JavaScript?

Этот вопрос может стать полным развалом мира для многих, потому что ответ Нет.


В ES5 (выпущенной в 2009 году) в JavaScript не было таких ключевых слов, как import, include или require.

ES6 экономит время (выпущено в 2015 году), предлагая ключевое слово import (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import), но ни один браузер не реализует это.

Если вы используете Babel 6.18.0 и переносите только с опцией ES2015

import myDefault from "my-module";

вы снова получите require.

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

Это потому, что require означает, что модуль будет загружен из Node.js. Node.js будет обрабатывать все, начиная от чтения файлов системного уровня и заканчивая переносом функций в модуль.

Потому что в JavaScript функции являются единственными обертками для представления модулей.

Я сильно запутался в CommonJS и AMD?

И CommonJS, и AMD - это всего лишь два разных метода преодоления "дефекта" JavaScript для умной загрузки модулей.