Отношения между CommonJS, AMD и RequireJS?
Я все еще очень озадачен CommonJS, AMD и RequireJS. Даже после прочтения много.
Я знаю, что CommonJS (ранее ServerJS) - это группа для определения некоторых спецификаций JavaScript (например, модулей), когда язык используется вне браузера. Спецификация модулей CommonJS имеет некоторую реализацию, такую как Node.js или RingoJS, верно?
Какова связь между CommonJS, определением асинхронного модуля (AMD) и RequireJS? Является ли RequireJS реализацией определения модуля CommonJS? Если да, то что такое AMD?
5 ответов
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, которая разработана для соответствия среде браузера ( источник). Судя по всему, 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"; };
});
Я надеюсь, что это помогает уточнить вещи!
CommonJS - это нечто большее, это проект, который определяет общий API и экосистему для JavaScript. Одной из частей CommonJS является спецификация модуля. Node.js и RingoJS являются средами выполнения JavaScript на стороне сервера, и да, оба они реализуют модули, основанные на спецификации модуля CommonJS.
AMD (Asynchronous Module Definition) - это еще одна спецификация для модулей. RequireJS, пожалуй, самая популярная реализация AMD. Одним из основных отличий от CommonJS является то, что AMD указывает, что модули загружаются асинхронно - это означает, что модули загружаются параллельно, а не блокируют выполнение, ожидая завершения загрузки.
В связи с этим AMD чаще используется в разработке JavaScript на стороне клиента (в браузере), а модули CommonJS обычно используются на стороне сервера. Однако вы можете использовать любую спецификацию модуля в любой среде - например, RequireJS предлагает инструкции по запуску в Node.js, а http://browserify.org/ - это реализация модуля CommonJS, которая может работать в браузере.
Краткий ответ:
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.
Источники:
AMD:
- Один браузер-первый подход
- Выбор асинхронного поведения и упрощенной обратной совместимости
- У этого нет никакого понятия Файлового ввода-вывода.
- Он поддерживает объекты, функции, конструкторы, строки, JSON и многие другие типы модулей.
CommonJS:
- Один сервер-первый подход
- Предполагая синхронное поведение
- Охватите более широкий круг проблем, таких как ввод-вывод, файловая система, обещания и многое другое.
- Поддерживает развернутые модули, может показаться немного ближе к спецификациям ES.next/Harmony, освобождая вас от оболочки define(), который
AMD
навязывает. - Поддерживайте только объекты как модули.
Вполне нормально организовать модульную программу JavaScript в несколько файлов и вызвать child-modules
от main js module
,
Дело в том, что JavaScript этого не обеспечивает. Даже сегодня в последних версиях браузера Chrome и FF.
Но есть ли в JavaScript ключевое слово для вызова другого модуля JavaScript?
Этот вопрос может быть полным крахом мира для многих, потому что ответ - нет.
В ES5 (выпущенной в 2009 году) в JavaScript не было ключевых слов, таких как import, include или require.
ES6 экономит время (выпущено в 2015 году), предлагая ключевое слово импорта ( 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 для умной загрузки модулей.
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.
Ресурсы: