Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Монолитный спагетти-код
• script.js, содержащий код всего сайта
• множество глобальных объектов, нет инкапсуляции,
конфлик...
JavaScript модуль
(function () {
var privVar
function privFunc() {
}
return {
pubFunc: function () {
}
}
})()
• реализация...
Использование модулей
• модули зависят от других модулей
• модули нужно загружать
• и только когда это необходимо
Нужно ст...
AMD
Asynchronous Module Definition
https://github.com/amdjs/amdjs-api/wiki/AMD
Стандартный способ определения модуля с учет...
AMD: id
define(id?, dependencies?, factory);
• строковый идентификатор — имя модуля
• необязателен, если не указан — иденти...
AMD: dependencies
define(id?, dependencies?, factory);
• массив идентификаторов зависимостей
• зависимости разрешаются пере...
AMD: factory
define(id?, dependencies?, factory);
• фабричная функция или объект
• функция выполняется только один раз
• во...
AMD: factory
Специальные зависимости:
require функция получения объекта загруженного модуля
exports список экспортируемых ...
Require.js
http://requirejs.org
• одна из реализаций AMD (самая популярная)
• базовый стандарт + различные дополнения
• во...
Базовый API
Определение
define([
’dep1’, ’dep2’
], function(dep1, dep2) {
...
});
define({
color: "black",
size: "unisize"...
Модули в Require.js
• один файл — один модуль
• объединение в один файл только оптимизатором
• не надо указывать имен — эт...
Бонус — JSONP
require(
["http://site.com/api/data.json?callback=define"],
function (data) {
//The data object will be the ...
Конфигурирование
requirejs.config(options)
basePath основной путь к загружаемым модулям
paths отдельные пути к различным пр...
Структура модулей приложения
www/
js/
app/ код приложения
lib/ библиотечные модули
lib1.js
lib2.js
common.js код, общий дл...
Структура модулей библиотек
www/js/lib/ внешние библиотеки
jquery/
fancybox.js плагины jQuery
easing.js
jquery-ui/
timepic...
Базовая конфигурация
config.js
require.config({
baseUrl: "/js/lib",
paths: {
"app": "/js/app"
}
});
common.js
define([
’jqu...
Загрузка модулей
Сначала загрузчик, потом конфиг, все остальное только после
конфига, чтобы проинициализировались пути.
<s...
Адаптация существующего кода
Проблемы:
• всегда глобальная область видимости
• вызов глобальных функций непосредственно из...
Что делать: модули
• группируем код по функциональности
• разбиваем на функции
• функции используются другими модулями —
б...
Модуль-функция
define([
’jquery’,
’app/lib/ui’
], function ($, ui) {
$(function () {
setup();
$(window).resize(resize);
})...
Модуль-библиотека
define([
’jquery’,
], function($) {
var privateVar;
return {
slider: function (id) {
...
}
}
function pr...
Что делать: глобальные объекты
В идеале — не использовать, не получается — использование и
явный экспорт с помощью window....
Что делать: inline-код в HTML
• <script> — выносим в страничные модули
• onclick ... — обычной привязкой событий
• компром...
Что делать: jQuery-плагины
• jQuery плагины должны быть AMD-модулями для
асинхронной загрузки
• не забываем про зависимост...
Внешние библиотеки — если
ничего не помогает
shim config
requirejs.config({
shim: {
’module’: {
deps: [’underscore’, ’jquer...
AMD/Require — архитектурные
преимущества
• минимальный API
• отсутствие жесткой структуры
• отсутствие глобального объекта...
Что читать
• https://github.com/amdjs/amdjs-api/wiki/AMD —
стандарт AMD
• http://requirejs.org — документация по Require.j...
Upcoming SlideShare
Loading in …5
×

RequireJS і Magento 2

708 views

Published on

"RequireJS і Magento 2"
Александр Короп
19.12.2015 - Magento 2 Release Event Chernivtsi
#m2cv

Published in: Software
  • Be the first to comment

RequireJS і Magento 2

  1. 1. Монолитный спагетти-код • script.js, содержащий код всего сайта • множество глобальных объектов, нет инкапсуляции, конфликты • функциональность разбросана внутри script.js и inline-скриптов • местами inline-код Нет разделения сложной задачи на более простые — любая задача будет сложной. Нужна модульность. 2 / 28
  2. 2. JavaScript модуль (function () { var privVar function privFunc() { } return { pubFunc: function () { } } })() • реализация скрыта • нет глобальных переменных • простой внешний фасад для сложной внутренней реализации • отдельная единица загрузки 3 / 28
  3. 3. Использование модулей • модули зависят от других модулей • модули нужно загружать • и только когда это необходимо Нужно стандартное решение: • обеспечивающее загрузку по требованию • гарантирующую подгрузку зависимостей • делающее это эффективно 4 / 28
  4. 4. AMD Asynchronous Module Definition https://github.com/amdjs/amdjs-api/wiki/AMD Стандартный способ определения модуля с учетом зависимостей и возможностью асинхронной загрузки. define(id?, dependencies?, factory); 5 / 28
  5. 5. AMD: id define(id?, dependencies?, factory); • строковый идентификатор — имя модуля • необязателен, если не указан — идентификатор, который был использован для загрузки файла • всегда абсолютный, относительные имена не допускаются 6 / 28
  6. 6. AMD: dependencies define(id?, dependencies?, factory); • массив идентификаторов зависимостей • зависимости разрешаются перед запуском factory • экземпляры зависимостей передаются в factory в соответствующих по порядку аргументах • относительные идентификаторы — относительно загружаемого модуля • по умолчанию [’require’, ’exports’, ’module’] 7 / 28
  7. 7. AMD: factory define(id?, dependencies?, factory); • фабричная функция или объект • функция выполняется только один раз • возвращаемое значение функции — экспортируемое значение модуля • объект непосредственно присваивается экспортируемому значению 8 / 28
  8. 8. AMD: factory Специальные зависимости: require функция получения объекта загруженного модуля exports список экспортируемых значений define( ’alpha’, [’require’, ’exports’, ’beta’], function(require, exports) { exports.verb = function () { return require(’beta’).something(); } }); 9 / 28
  9. 9. Require.js http://requirejs.org • одна из реализаций AMD (самая популярная) • базовый стандарт + различные дополнения • возможность статического анализа кода и последующая оптимизация за счет сборки и компрессии модулей 10 / 28
  10. 10. Базовый API Определение define([ ’dep1’, ’dep2’ ], function(dep1, dep2) { ... }); define({ color: "black", size: "unisize" }); Загрузка require([ ’dep1’, ’dep2’ ], function(dep1, dep2) { ... }); Конфигурирование requirejs.config({ baseUrl: ’/another/path’, ... }); 11 / 28
  11. 11. Модули в Require.js • один файл — один модуль • объединение в один файл только оптимизатором • не надо указывать имен — этим занимается оптимизатор • модуль require — различные полезные утилиты • относительные пути — с помощью модуля require: define(function(require) { var mod = require("./relative/name"); }); define(["require"], function(require) { var cssUrl = require.toUrl("./style.css"); }); 12 / 28
  12. 12. Бонус — JSONP require( ["http://site.com/api/data.json?callback=define"], function (data) { //The data object will be the API response // for the JSONP data call. console.log(data); } ); Предназначено для использования при начальной инициализации приложения. 13 / 28
  13. 13. Конфигурирование requirejs.config(options) basePath основной путь к загружаемым модулям paths отдельные пути к различным префиксам shim внешние определения для не модульных скриптов map псевдонимы для модулей config параметры конфигурации модулей callback пользовательский обрабочик события загрузки urlArgs дополнительные параметры для запроса ... 14 / 28
  14. 14. Структура модулей приложения www/ js/ app/ код приложения lib/ библиотечные модули lib1.js lib2.js common.js код, общий для всех страниц page1.js код для отдельной страницы page2.js lib/ внешние библиотеки config.js конфигурация require.js Приложение отдельно, библиотеки отдельно, постраничное разбиение — если необходимо. 15 / 28
  15. 15. Структура модулей библиотек www/js/lib/ внешние библиотеки jquery/ fancybox.js плагины jQuery easing.js jquery-ui/ timepicker-addon.js плагины jquery-ui jquery.js jQuery jquery-ui.js jQuery UI require.js Require.js Используем единую схему именования файлов плагинов для получения простых имен соответствующих модулей 16 / 28
  16. 16. Базовая конфигурация config.js require.config({ baseUrl: "/js/lib", paths: { "app": "/js/app" } }); common.js define([ ’jquery’, ’app/lib/ui’ ], function($, ui) { ... }); 17 / 28
  17. 17. Загрузка модулей Сначала загрузчик, потом конфиг, все остальное только после конфига, чтобы проинициализировались пути. <script src="js/lib/require.js"></script> <script> require([’js/config’], function(config) { require([’app/common’, ’app/page1’]); }); </script> Сокращенная форма для одностраничных приложений: <script src="js/lib/require.js" data-main="js/main.js"> 18 / 28
  18. 18. Адаптация существующего кода Проблемы: • всегда глобальная область видимости • вызов глобальных функций непосредственно из HTML-кода • inline код в HTML • jQuery-плагины — не AMD модули 19 / 28
  19. 19. Что делать: модули • группируем код по функциональности • разбиваем на функции • функции используются другими модулями — библиотечный модуль, возвращает объект • нужна только настройка DOM — просто выполняем функцию • все переменные и функции определяем внутри модуля, снаружи они недоступны 20 / 28
  20. 20. Модуль-функция define([ ’jquery’, ’app/lib/ui’ ], function ($, ui) { $(function () { setup(); $(window).resize(resize); }); function setup() { ui.slider(’#slider’); } function resize() {...} }); 21 / 28
  21. 21. Модуль-библиотека define([ ’jquery’, ], function($) { var privateVar; return { slider: function (id) { ... } } function privateFunc() { ... } }); 22 / 28
  22. 22. Что делать: глобальные объекты В идеале — не использовать, не получается — использование и явный экспорт с помощью window. function () { window.checkForm = validate; function validate(form) { var mode = window.globalMode ... } } Используем window, легче отследить и потом избавиться. 23 / 28
  23. 23. Что делать: inline-код в HTML • <script> — выносим в страничные модули • onclick ... — обычной привязкой событий • компромиссный вариант — группировать весь inline-код require([’js/config’], function(config) { require([ ’jquery’, ’app/common’, ’app/page1’ ], function ($) { // тут весь inline-код. } }); 24 / 28
  24. 24. Что делать: jQuery-плагины • jQuery плагины должны быть AMD-модулями для асинхронной загрузки • не забываем про зависимости (function (root) { var amdExports; define([’jquery’], function (jQuery) { ... }.call(root)); return amdExports; }); }(this)); Преобразование вручную или программой, например, volo. 25 / 28
  25. 25. Внешние библиотеки — если ничего не помогает shim config requirejs.config({ shim: { ’module’: { deps: [’underscore’, ’jquery’], exports: ’Module’ }); 26 / 28
  26. 26. AMD/Require — архитектурные преимущества • минимальный API • отсутствие жесткой структуры • отсутствие глобального объекта приложения • соответствие базовым паттернам JavaScript • легко сконвертировать существующий код 27 / 28
  27. 27. Что читать • https://github.com/amdjs/amdjs-api/wiki/AMD — стандарт AMD • http://requirejs.org — документация по Require.js • https://github.com/requirejs/example-multipage — пример для мультистраничных сайтов • http://addyosmani.com/writing-modular-js/ — Writing modular JavaScript with AMD, CommonJS and ES Harmony. 28 / 28

×