- PVSM.RU - https://www.pvsm.ru -
При разработке приложений с модульной структурой на JavaScript возникает две проблемы:
Обе эти задачи решаются при использовании подхода Asynchronous Module Definition [1]. Он сводится к описанию модулей функцией define и подключению их с помощью require. На данный момент есть несколько инструментов, реализующих AMD. Я начал своё знакомство с ними с RequireJS [2] и был удивлён, на сколько удобно и просто можно описывать зависимости модулей. Расскажу, как это работает, на простом примере.
Имеем следующую структуру каталогов:
siteroot/
js/
app.js
require.js
jquery.js
mymodule.js
index.html
Для начала, подключим в index.html загрузчик. Будем использовать RequireJS:
<script data-main="/js/app" src="/js/require.js"></script>
Отлично, это единственный тег script, который нам нужен. Остальную работу по подключению JS сделает загрузчик. Указанный в data-атрибуте файл (расширение .js для краткости в RequireJS всегда опускается) будет своеобразной точкой входа нашего приложения. В нём мы сможем подключить необходимые модули с помощью require и совершить задуманные действия.
Опишем наш модуль в /js/module.js с помощью define:
define(
'mymodule',
['jquery'],
function( $ ){
return {
foo : 'bar'
};
}
);
Первый аргумент — строка, название модуля, не обязателен. Вторым аргументом передаются зависимости в виде массива строк, также опционально. Третий аргумент — функция-фабрика, которая выполняется только после удовлетворения всех зависимостей (загрузки перечисленных файлов). В неё в качестве аргументов передаются экспортируемые зависимостями переменные. А возвращать она должна сам модуль. В данном случае это объект с одним полем.
В /js/app.js подключим нужные модули с помощью JS и выполним свой код:
require(
['mymodule', 'jquery'],
function( Module, $ ){
$('body').append( Module.foo );
}
);
Module при этом не будет доступна в глобальной области видимости, как и другие переменные, экспортируемые библиотеками из зависимостей. Не смотря на то, что библиотека jQuery с версии 1.7 поддерживает AMD-архитектуру, она является исключением: экспортирует свой доллар в глобальную область видимости. Скорее всего, это сделано для сохранения совместимости с армией плагинов, написанных за многие годы.
RequireJS обладает рядом параметров, которые можно передавать перед использованием. Для этого служит объект require.config.
Что делать, если вам необходимо подключить модуль, которая не оформлен в виде AMD и экспортирует переменную в глобальную область видимости? Можно, конечно, модифицировать его исходный код, но это плохая практика. Для описания таких модулей служит параметр shim. Можно вручную указать его зависимости и экспортируемую переменную, и он станет частью нашего приложения наравне с другими AMD-парнями:
require.config = {
shim: {
'oldmodule' : {
depts: [],
exports: 'OldModule'
}
}
};
Теперь можно указывать его в качестве зависимости:
require(
['mymodule', 'jquery', 'oldmodule'],
function(){}
);
Помимо shim есть ещё много параметров: корневая директория подключения файлов baseUrl, псевдонимы для более удобного подключения paths, и т.д.
Надеюсь, концепция AMD зацепила вас, так же, как и меня. Она помогает избежать хаоса при использовании большого количества JS-файлов в разработке, подталкивает к написанию реюзабельного кода, снимает ответственность за подключение файлов с бэкенда. А если у вас реально большое MVC-приложение из пары десятков файлов, то подобная система просто незаменима.
На прощание, приведу несколько ссылок, которые помогут продолжить изучение вопроса:
Исходный код из статьи доступен в репозитории на GitHub [4].
Happy hacking!
Автор: clslrns
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/16171
Ссылки в тексте:
[1] Asynchronous Module Definition: https://github.com/amdjs/amdjs-api/wiki/AMD
[2] RequireJS: http://requirejs.org
[3] Writing Modular JavaScript With AMD, CommonJS & ES Harmony: http://addyosmani.com/writing-modular-js/
[4] в репозитории на GitHub: http://github.com/clslrns/requirejs-test
Нажмите здесь для печати.