- PVSM.RU - https://www.pvsm.ru -
Hello World,
Helios Kernel [1] — это библиотека для управления зависимостями между javascript-модуями, реализующая «классический» подход, часто встречаемый в других языках и средах — с помощью функции include().
Такой способ отличается от других подходов своей простотой: зависимости перечисляются в начале модуля по точному пути к файлу, тело модуля содержит код, который выполняется после загрузки зависимостей модуля.
Helios Kernel придерживается принципа KISS [2], поэтому здесь отсутствуют некоторые возможности, которые сегодня принято ожидать от библиотеки по управлению зависимостями. При использовании Helios Kernel не нужно описывать конфиг с правилами поиска путей для разных модулей, или экспортировать библиотечные функци через специальный объект. Но эта библиотека была написана как раз потому, что хотелось просто подключать нужные модули и писать код, не натыкаясь на крутые возможности при указании каждой новой зависимости.
Helios Kernel поддерживает динамическую загрузку (и выгрузку) зависимостей в рантайме, а сама библиотека и формат модулей являются совместимыми между nodejs и броузерной средой — то есть модули можно использовать без изменений или трансляции.
В этой статье классический подход реализованный в Helios Kernel сравнивается с управлением зависимостями с помощью RequireJS [3] и показывается, каким образом подход Helios Kernel позволяет избежать некоторых сложностей.
Helios Kernel обладает такими особенностями:
Поэтому описание зависимости между двумя модулями выглядит следующим образом.
Библиотечный модуль myLibrary.js, объявляющий некоторую функциональность:
init = function() {
// объявление (глобального) библиотечного объекта
myLibrary = {};
// библиотечная функция
myLibrary.writeHello = function() {
console.log("Hello World!");
}
}
И модуль подключающий и использующий эту библиотеку:
include("path/to/myLibrary.js");
init = function() {
// здесь библиотека подключена и можно её использовать
myLibrary.writeHello();
}
Здесь для «экспорта» библиотечного объекта используется определение глобальной переменной myLibrary в первом модуле. Сейчас такой способ принято считать «неправильным», потому что к глобальным объектам можно получить доступ откуда угодно. Но я его здесь использую, поскольку он является самым наглядным в качестве примера. Helios Kernel не накладывает никаких ограничений на способ передачи объектов между модулями: внутри функции init может быть любой код. В том числе там можно определить и функцию-фабрику, которая будет возвращать только «экспортируемый объект».
Но если нужно только определять локальные переменные модуля, для этого можно использовать область видимости функции init().
Далее я буду приводить примеры, в которых использование Helios Kernel позволяет сделать код проще по сравнению с RequireJS
Формат описания модуля с зависимостями выглядит так:
RequireJS | Helios Kernel |
---|---|
|
|
Способ экспортирования библиотечных объектов, используемый в RequireJS заставляет указывать название зависимости дважды — один раз имя модуля, где находится зависимость, второй раз — имя аргумента, куда эта зависимость будет экспортирована.
Это особенно усложняет читаемость модулей RequireJS, когда зависимостей становится больше:
RequireJS | Helios Kernel |
---|---|
|
|
Для того чтобы упростить такой код, в RequireJS был даже придуман альтернативный способ описания зависимостей, simplified CommmonJS [4]. Используя этот приём, можно описывать зависимости следующим образом:
define(
[ 'dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7' ],
function (require) {
var dep1 = require('dep1'),
dep2 = require('dep2'),
dep3 = require('dep3'),
dep4 = require('dep4'),
dep5 = require('dep5'),
dep6 = require('dep6'),
dep7 = require('dep7');
// ...
}
});
Такая запись позволяет немного упростить форматирование и улучшить читаемость, но даже здесь приходится упоминать название зависимостей несколько раз. Кроме того, этот синтаксический сахар добавляет очередное усложнение в виде ещё одного способа обращения к зависимостям.
Helios Kernel позволяет всего этого избежать. Дополнительная зависимость требует только одного упоминания с помощью include().
Предположим что есть несколько модулей, которые часто используются совместно во многих частях проекта. Или есть библиотека, которая состоит из нескольких частей, и нужно получить все эти части разом. Самый простой способ получать несколько модулей — подключать их все явно каждый раз там, где они нужны.
Но ведь большой проект для того и разбивается на модули, чтобы не дублировать лишний код. Поэтому можно написать один общий модуль, который будет подключать остальные.
Однако в случае с RequireJS нужно будет ещё экспортировать требуемые зависимости и «пробросить» их через экспортируемый объект общего модуля.
В случае с Helios Kernel достаточно просто перечислить зависимости:
RequireJS | Helios Kernel |
---|---|
|
|
Для общего модуля, написанного в формате Helios Kernel даже не нужно описывать функцию init(). Это также упрощает читаемость — если заглянуть в код этого модуля — сразу видно, что он не совершает никаких действий, а только подключает дополнительные моудли.
А вот в случае с общим модулем с CommonJS придётся ещё и переписать все случаи его экспорта. Если раньше к отдельным экспортированным частям нужно было обращаться как dep1, dep2,..., то теперь это нужно заменить на depCommon.dep1, depCommon.dep2,…
Речь идёт о библиотеках, которые предполагается подключать на html-страницу с помощью тега script.
Формат модуля Helios Kernel гораздо ближе к обычным библиотекам, потому что внутри функции init() может содержаться любой код. Поэтому для того, чтобы превратить обычную библиотеку в модуль, достаточно обернуть её в определение функции init(), и после этого её можно будет подключить с помощью include().
В случае с RequireJS конвертировать библиотеку в модуль гораздо сложнее, потому что модуль должен экспортировать определяемые объекты, и пришлось бы делать рефакторинг. Вместо этого предлагается описать модуль в конфиге с помощью аттрибута shim [5]. Однако даже такой подход может привести к проблемам [6].
Для того чтобы использовать модули RequireJS на сервере в среде nodejs, можно воспользоваться библиотекой r.js [7], которая позволяет такие модули подключать в nodejs.
В обратную сторону: проект, написанный в формате модулей CommonJS, используемом в node, можно отконвертировать в веб-библиотеку с помощью browserify [8]. Но это получится не модуль, а большой бандл, подключаемый тегом script (или конфигом shim в RequireJS).
Helios Kernel упрощает эту задачу за счёт того, что модули работают без изменений и конвертации на обоих платформах.
Буду рад советам и комментариям.
Сайт: http://asvd.github.io/helios-kernel/ [1]
Код: https://github.com/asvd/helios-kernel/releases/download/v0.9.4/helios-kernel-0.9.4.tar.gz [9]
Гитхаб: https://github.com/asvd/helios-kernel [10]
Автор: xpostman
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/46739
Ссылки в тексте:
[1] Helios Kernel: http://asvd.github.io/helios-kernel/
[2] KISS: http://en.wikipedia.org/wiki/KISS_principle
[3] RequireJS: http://requirejs.org/
[4] simplified CommmonJS: http://requirejs.org/docs/api.html#cjsmodule
[5] shim: http://requirejs.org/docs/api.html#config-shim
[6] может привести к проблемам: http://esa-matti.suuronen.org/blog/2013/03/22/journey-from-requirejs-to-browserify/#disappearing-globals
[7] r.js: http://requirejs.org/docs/node.html
[8] browserify: http://browserify.org/
[9] https://github.com/asvd/helios-kernel/releases/download/v0.9.4/helios-kernel-0.9.4.tar.gz: https://github.com/asvd/helios-kernel/releases/download/v0.9.4/helios-kernel-0.9.4.tar.gz
[10] https://github.com/asvd/helios-kernel: https://github.com/asvd/helios-kernel
[11] Источник: http://habrahabr.ru/post/199162/
Нажмите здесь для печати.