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

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

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

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

Является ли RequireJS реализацией определения модуля CommonJS? Если да, то что тогда AMD?


person gremo    schedule 13.05.2013    source источник
comment
Прочитав requirejs.org/docs/whyamd.html, можно многое прояснить, поскольку он упоминает их все. (разместив его как комментарий, так как я не считаю это полным ответом).   -  person mmutilva    schedule 29.12.2013
comment
Могу я спросить или добавить еще; Как и где операторы импорта ES2015 вписываются во все это; например импортировать Ember из ember;   -  person copenndthagen    schedule 28.02.2016
comment
Также существует systemjs, который загружает любой из поддерживаемых форматов модулей JS, например (CommonJS, UMD, AMD, ES6).   -  person Andy    schedule 20.04.2017


Ответы (6)


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

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 для экспорта содержимого модуля и идентификатор модуля (который описывает расположение рассматриваемого модуля по отношению к этому модулю), который используется для запроса зависимостей. (исходный код). CommonJS имеет различные реализации, включая упомянутый вами Node.js.

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

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

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

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

  • 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"; };
});

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

person jakee    schedule 13.05.2013
comment
Посмотрите проект uRequire.org, который устраняет пробелы в двух форматах: запись в одном (или обоих), развертывание в любом из двух или простой ‹script› - person Angelos Pikoulas; 24.08.2013
comment
Итак ..., если requirejs может загружать модули commonjs, тогда не должно быть проблем с загрузкой модулей node (поскольку они используют подход commonjs), верно? Если мое первое утверждение верно - можно ли тогда загрузить модули requirejs в модуль узла? - person orustammanapov; 29.08.2013
comment
@orustammanapov В файлах CommmonJS не будет оболочки define(...) в последнем примере этого ответа. Препроцессор JS на стороне сервера может добавить эту оболочку (это будет просто текстовый JS до и после существующего определения CommonJS). - person Carl G; 26.01.2014
comment
К вашему сведению, Browserify теперь позволит вам использовать CommonJS в браузере. - person Eruant; 30.01.2014
comment
@Eruant Но он все еще не имеет такой асинхронной природы, как AMD. - person Inanc Gumus; 16.05.2014
comment
Написание модульных js, напишите addyosmani, в котором также есть подраздел, в котором обсуждается, является ли CommonJS подходит для браузера или нет. - person Sharat M R; 25.12.2014
comment
Причина, по которой CommonJS не подходит для браузера, как указано в документации RequireJS - CommonJS require () - это синхронный вызов, ожидается, что модуль вернет модуль немедленно. Это плохо работает в браузере. Дополнительная информация здесь. - person maheshsenni; 06.01.2015
comment
@deeperx - Разве это не имеет значения, поскольку он объединяет файлы, поэтому сервер должен обслуживать только один? - person aaaaaa; 26.01.2015
comment
@aaaaaa вы можете включить некоторые функции в зависимости от запроса пользователя; так что асинхронный характер AMD может пригодиться. - person Inanc Gumus; 04.02.2015
comment
Могу я спросить или добавить еще; Как и где операторы импорта ES2015 вписываются во все это; например импортировать Ember из ember; - person copenndthagen; 27.02.2016
comment
Отличная запись, не могли бы вы дополнить ее, возможно, объяснением CMD (github.com /cmdjs/specification/blob/master/draft/module.md)? Популярно в Китае. - person jayarjo; 01.09.2016
comment
@jayarjo: Нет, не смог. - person jakee; 11.09.2016

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

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

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

person Nate    schedule 13.05.2013
comment
Почему домашняя страница CommonJS такая ужасная ... Я просто пытаюсь просмотреть официальную спецификацию. Имеются синтаксические ошибки, неполная документация, а страница вики не разрешается. - person taco; 21.03.2015
comment
Это не то, что означает асинхронная загрузка модулей. Возможно, вы говорите о динамической / ленивой загрузке. С помощью async вы предлагаете загрузить файл, а затем через некоторое время он перезвонит, когда завершит загрузку. С синхронизацией вы предлагаете загрузить файл, а затем весь поток блокируется, пока этот файл не завершит загрузку; никакой дополнительный код не выполняется, пока файл не загрузится. Первый может дать лучшую производительность за счет непредсказуемости, в то время как второй может давать одни и те же результаты каждый раз и, таким образом, более предсказуем. Обратите внимание, что эти причуды можно смягчить с помощью различных оптимизаций. - person perry; 08.08.2015
comment
Спасибо за ответ. Теперь, когда модули являются официальными в JS с ES2015, означает ли это, что они предпочтительнее AMD или обычного JS? - person Akhoy; 29.04.2016
comment
Это не значит, что им отдают предпочтение. Все зависит от потребностей разработчика. Я не думаю, что не оставлять никаких вариантов и переходить на модули ES6 - это особенно хорошая идея. Однако, используя хороший UMD, вы можете решить эту проблему. Загрузка пакетов CommonJS, синхронизированных с AMD, в целом является хорошей (лучшей) идеей (для улучшения производительности). Очевидно, если вы чувствуете, что должны иметь больше контроля. И ты должен. - person Maciej Sitko; 06.05.2016

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

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

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

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

Взято из книги Адди Османи.

// 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. Аргументы вокруг того, какой формат лучше, утверждают, что CommonJS пытается охватить более широкий круг проблем и что он лучше подходит для разработки на стороне сервера, учитывая его синхронный характер, и что AMD лучше подходит для разработки на стороне клиента (браузера), учитывая его асинхронный характер и тот факт, что он уходит своими корнями в реализацию объявления модуля Dojo.

Источники:

person mmutilva    schedule 29.12.2013
comment
Видеть код, а не описания, помогает! :) AMD compliant на самом деле RequireJS, верно? - person Asim K T; 04.09.2016
comment
Я что-то упустил или есть ошибка? Вы определяете package / lib, но затем требуете package / myModule. - person RullDawg; 13.12.2016
comment
Мне всегда нравится читать немного истории о том, почему что-то такое, как оно есть! Спасибо за предоставленный фон! - person Andru; 05.02.2018
comment
@RullDawg Нет, «package / lib» здесь не определяется, здесь используется сторонняя зависимость. - person Robert Siemer; 01.02.2020

Цитирование

AMD:

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

CommonJS:

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

Совершенно нормально организовать модульную программу 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 для интеллектуальной загрузки модулей.

person prosti    schedule 30.10.2016
comment
Следует обновить свой ответ, потому что теперь все современные браузеры поддерживают import - person vsync; 26.10.2019
comment
@vsync, да, не стесняйтесь редактировать мой ответ, так как я уже некоторое время не слежу за этим сегментом. - person prosti; 28.10.2019

AMD

  • введен в JavaScript для масштабирования проекта JavaScript на несколько файлов
  • в основном используется в браузерных приложениях и библиотеках
  • популярной реализацией является RequireJS, Dojo Toolkit

CommonJS:

  • это спецификация для обработки большого количества функций, файлов и модулей большого проекта
  • начальное имя ServerJS, представленное Mozilla в январе 2009 г.
  • переименован в августе 2009 года в CommonJS, чтобы показать более широкую применимость API
  • изначально реализация были сервером, nodejs, настольными библиотеками

Пример

файл upper.js

exports.uppercase = str => str.toUpperCase()

файл main.js

const uppercaseModule = require('uppercase.js')
uppercaseModule.uppercase('test')

Резюме

  • AMD - одна из самых древних модульных систем, первоначально реализованная библиотека require.js.
  • CommonJS - модульная система, созданная для сервера Node.js.
  • UMD - еще одна модульная система, предлагаемая как универсальная, совместимая с AMD и CommonJS.

Ресурсы:

person Hafiz Shehbaz Ali    schedule 14.07.2020