CommonJS сейчас довольно популярен, широко используется не только в приложениях Node.js, но и для интерфейсных, одностраничных приложений, разработанных в фреймворках Angular, React. Эту статью я опубликовал в своем новом блоге, посвященном JavaScript, JavaScript.SH.
Почему CommonJS?
JavaScript широко известен своим использованием в качестве языка, основанного на браузере, наряду с HTML5, CSS, Dynamic DOM, пока у нас не появился Node.js, среда выполнения JavaScript, которая позволяет разработчикам писать независимые серверные приложения JavaScript. Браузеры используют тег HTML, ‹Script src=”…” /› для загрузки файлов JavaScript в браузеры.
Когда приложение имеет несколько файлов, разработчики должны разместить тег скрипта в правильном порядке, чтобы разрешить зависимости файлов, чтобы браузер мог загружать файлы приложения в правильном порядке без нарушения.
У нас есть несколько ограничений в JavaScript.
- JavaScript (ES5) не имеет пространства имен или концепции пакета, как в C++/C# или в Java.
- JavaScript имеет только два уровня области видимости. Один из них — это глобальная область, а второй — область действия на функциональном уровне.
- Глобальная область действия болезненна, когда приложение вводит одно и то же имя переменной в двух разных файлах (коллизия), и любой из них может существовать.
В то время как проблемы с глобальными переменными могут быть решены с помощью замыканий, т.е. включения кода JavaScript в функцию.
Отсутствие пакетов/пространства имен действительно является проблемой для приложений Node.js, особенно у нас есть много файлов в приложении, и в приложении нужно ссылаться на множество сторонних библиотек.
В CommonJS есть решение вышеупомянутых проблем.
Что такое CommonJS?
CommonJS — это спецификация, вы не найдете конкретной библиотеки JavaScript с таким названием. Группа независимых разработчиков начала работать над решением упомянутой выше проблемы, т.е. загрузки одного файла в другой файлы JavaScript, глобальные переменные, они придумали спецификацию.
CommonJS представлен ниже спецификаций.
- Каждый файл JavaScript является модулем
- Модуль (файл JavaScript) может иметь локальные переменные/функции в локальной области видимости, которые не должны конфликтовать с аналогичным именем переменной/функции, определенным в другом модуле (также известном как файл JavaScript)
- Модуль может иметь многократно используемые функции/переменные, которые можно использовать в другом файле, которые необходимо экспортировать из этого файла (module.exports, exports)
- Один модуль может ссылаться на другой модуль с помощью инструкции require
//math.js function log(message) { console.log("math ", message) } module.exports.add = function(a, b) { log("add"); return a + b; }; exports.sub = function(a, b) { log("sub"); return a - b; }
В файле math.js функция журнала строго локальна для файла math.js и не отображается за пределами файла.
добавить, подметоды доступны вне math.js, эти функции можно использовать в других файлах. CommonJS представил module.exports и exports (оба одинаковые, без различий) для экспорта функций, переменных вне файла.
Чтобы использовать методы add,sub в другом файле, CommonJS представил функцию require
//calc.js var math = require("./math") function log(message) { console.log("calc ", message) } log(math.add(1,2)) log(math.add(10 - 5))
Приведенный выше код должен печатать
math add calc 3 math sub calc 5
Оба файла содержат функцию журнала, которая является локальной для конкретного файла. CommonJS позволяет избежать конфликта имен между файлами. Нам требуется ("./math") в основном загрузить файл math.js в текущий каталог (./)
Как это работает в Node.js?
Node.js реализует спецификацию Common.JS для зависимостей модулей. Когда мы используем оператор require, Node.js в основном загружает содержимое файла JavaScript в память, затем оборачивает содержимое файла в тело функции (Closure), чтобы избежать конфликтов глобальных переменных, node.js передает модуль, экспортирует как параметры функции.
Посмотрите, как работает реализация Node.js CommonJS require
function (module, exports) { //below content inserted from math.js file function log(message) { console.log("math ", message) } module.exports.add = function(a, b) { log("add"); return a + b; }; exports.sub = function(a, b) { log("sub"); return a - b; } // return exports; }
Поскольку модули CommonJS не являются частью языковой спецификации ES5, браузеры не поддерживают экспорты, module.exports и требуют функции.
Поддержка в браузерах
Если мы хотим использовать модули в стиле CommonJS в браузерах, у нас есть различные варианты через внешние библиотеки.
- SystemJS (работает на стороне клиента, загружает файлы и оборачивает их в браузере)
- Browserify (работает на node.js, создает загружаемый браузером единый файл пакета javascript из всех файлов javascript, указанных в функции require().
- Webpack (работает на node.js, работает аналогично Browserify, но с другими функциями)
Современные веб-приложения, созданные с использованием фреймворков Angular, React, с использованием языков ES6, TypeScript (транспиляторы Babel, TypeScript), используют CommonJS по умолчанию при генерации ES6 в ES5 или TypeScript в ES5.