YUI 3 - модульная архитектура и динамическая загрузка приложения от Yahoo! Пётр Мязин YUI is a free, open source JavaScript and CSS library for building richly interactive web applications. http://yuilibrary.com Веб-решения для управления логистикой и цепями поставок в международной компании экспедиторе Panalpina. Представительства в 80 странах мира. Мы делаем динамические интерфесы с большим количеством виджетов и интерактива. Основные JS виджеты – это различные калькуляторы тарифов перевозок, быстрый поиск и ввод информации о грузах. • YUI 2 • jQuery • ExtJS 3 • YUI 3 • AngularJS • История развития • Основные возможности • Поддерживаемые платформы • Статическая загрузка vs динамическая загрузка • Динамическая загрузка самого фреймворка • Создание своих модулей в стиле YUI • Описание зависимостей между модулями • Динамическая загрузка сторонних библиотек 2005 – внутренняя разработка Yahoo! 2006 февраль – первый публичный релиз YUI 2 2009 сентябрь - релиз переписанного с нуля YUI 3.0 2006 – yui-ext как дополнительный набор виджетов к YUI 2006 осень – библиотека приобретает популярность и начинает называться просто Ext 2007 – ExtJS 1.0 Основные возможности • • • • • Кроссбраузерная работа с DOM и событиями Анимации Утилиты (Handelbars, History, Uploader, Pjax, Promise, …) Виджеты (Autocomplete, Charts, DataTable, Panel, TabView, …) App Framework • MVC • Routing • • • • • Y.Test – более 20000 тестов Сборка с использованием Grunt, минификация Uglifyjs Открытая модель разработки через github Yahoo! CDN Лицензия BSD Поддержка браузеров WidgetA.js WidgetB.js B1.js WidgetA.css Library.js Core.js Core.css B2.js Статическая загрузка <script <script <script <script <script <script src="Core.js"></script> src="Library.js"></script> src="WidgetA.js"></script> src="B1.js"></script> src="B2.js"></script> src="WidgetB.js"></script> или <script src="all.js"></script> или <script src="Core-and-Library.js"></script> <script src="WidgetA.js"></script> <script src="WidgetB-rollup.js"></script> Динамическая загрузка • Хотим загружать js и css по событиям от пользователя • Все зависимости должны разрешаться автоматически • Если какой-то из модулей уже загружен, повторно не загружаем • Асинхронная загрузка <script src=“…” async=“true”> Динамическая загрузка – вручную var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "/js/myfile.js"; var head = document.getElementsByTagName("head")[0]; head.appendChild(s); Динамическая загрузка в YUI • Библиотека разделена на ~250 модулей • Каждый модуль – это отдельный js или css файл • Между модулями существуют зависимости • yui-min.js – базовый файл, который знает всю карту зависимостей и умеет загружать модули динамически • По умолчанию файлы модулей загружаются из Yahoo! CDN • Загрузчик отправляет ОДИН http запрос к CDN с указанием всех требуемых модулей, получает минифицированную сборку Динамическая загрузка – с помощью YUI // Put the YUI seed file on your page. <script src="http://yui.yahooapis.com/3.10.3/build/yui/yui-min.js"></script> <script> // Create a YUI sandbox on your page. YUI().use('node', 'event', function (Y) { // The Node and Event modules are loaded and ready to use. // Your code goes here! }); </script> // Put the YUI seed file on your page. <script src="http://yui.yahooapis.com/3.10.3/build/yui/yui-min.js"></script> YUI().use('transition', function (Y) { // Fade away. Y.one('#fademe').transition({ duration: 1, // seconds opacity : 0 }); // Shrink to nothing. Y.one('#shrinkme').transition({ duration: 1, // seconds width : 0, height : 0 }); }); 1. yui-base (34.78 KB) 2. oop (2.14 KB) 3. features (4.90 KB) 4. dom-core (2.58 KB) 5. dom-base (6.16 KB) 6. color-base (2.98 KB) 7. dom-style (2.27 KB) 8. event-custom-base (11.95 KB) 9. selector-native (3.37 KB) 10. selector (0.08 KB) 11. node-core (9.52 KB) 12. node-base (6.11 KB) 13. event-base (7.17 KB) 14. node-style (0.48 KB) 15. transition (7.15 KB) <script type="text/javascript" src="http://yui.yahooapis.com/combo?3.10.3/yui-base/yui-basemin.js&3.10.3/oop/oop-min.js&3.10.3/features/features-min.js&3.10.3/dom-core/dom-coremin.js&3.10.3/dom-base/dom-base-min.js&3.10.3/color-base/color-base-min.js&3.10.3/domstyle/dom-style-min.js&3.10.3/event-custom-base/event-custom-base-min.js&3.10.3/selectornative/selector-native-min.js&3.10.3/selector/selector-min.js&3.10.3/node-core/node-coremin.js&3.10.3/node-base/node-base-min.js&3.10.3/event-base/event-basemin.js&3.10.3/node-style/node-style-min.js&3.10.3/transition/transition-min.js"></script> Опишем модуль в отдельном файле YUI.add('my-module', function (Y) { // Write your module code here, and make your module available on the Y // object if desired. Y.MyModule = { sayHello: function () { console.log('Hello!'); } }; }, '0.0.1', { requires: ['node', 'event'] }); Используем его на основной странице YUI().use('my-module', function (Y) { // The Y instance here is the same Y instance that was passed into // my-module's add() callback, so the Y.MyModule object that was created // there is now available here as well. Y.MyModule.sayHello(); }); Чтобы загрузчик знал откуда загружать наши собственные модули, нужно описать карту зависимостей и путей YUI.applyConfig({ "groups":{ "mylibs":{ "base": "path/to/jsfiles/", "modules":{ "my-module":{ "path":"MyModuleFile.js", "requires":["node", "event"] } } } } }); WidgetA.js WidgetB.js B1.js WidgetA.css Library.js Core.js Core.css B2.js "my-app-css": { base: "path/to/css/", modules: { "core-css": { path: "Core.css" }, "widget-a-css": { path: "WidgetA.css" } } } "my-app": { base: "path/to/js/", modules: { "core": { path: "Core.js", requires:["core-css"] }, "library": { path: "Library.js", requires:["core"] }, "widget-a": { path: "WidgetA.js", requires:["library", "widget-a-css"] }, "b1": { path: "B1.js", requires:["library"] }, "b2": { path: "B2.js", requires:["library"] }, "widget-b": { path: "WidgetB.js", requires:["b1", "b2"] } } } <script <script <script <script <script <script src="Core.js" async="true"></script> src="Library.js" async="true"></script> src="WidgetA.js" async="true"></script> src="B1.js" async="true"></script> src="B2.js" async="true"></script> src="WidgetB.js" async="true"></script> Файл WidgetB.js YUI.add('widget-b', function (Y) { //Этот код не будет запущен //пока все зависимости не будут удовлетворены }, '0.0.1', { requires: ['b1', 'b2'] }); Описывая карту зависимостей, можно: • Загружать файлы по одному или через комбозагрузчик (одинм http запросом) • Загружать raw, min или debug версии (к файлам будут добавлены суффиксы) • Загружать или нет на основе теста фич браузера (разные версии модуля под разные браузеры) • Разбить модули на группы и к каждой группе применить свой комплекс настроек Динамическая загрузка сторонних библиотек YUI.applyConfig({ "groups":{ "select2": { async: false, modules: { "select2": { path: "select2.min.js", requires: ["select2-css"] }, "select2-css": { path: "select2.css", type: "css" } } } } }); YUI Gallery – хостинг своих модулей в Yahoo! CDN • Инструменты shifter и yogi (node.js) помогают создать и покрыть тестами собственный YUI модуль • Можно опубликовать свой модуль в YUI Gallery • Любой разработчик может использовать модуль из YUI Gallery YUI().use("gallery-myawesomemodule", function(Y) { Y.MyAwesomeModule.sayHallo(); }); • История развития • Основные возможности • Поддерживаемые платформы • Статическая загрузка vs динамическая загрузка • Динамическая загрузка самого фреймворка • Создание своих модулей в стиле YUI • Описание зависимостей между модулями • Динамическая загрузка сторонних библиотек