modules and assembling of javascript (in russian)
DESCRIPTION
TRANSCRIPT
Михаил Давыдов JavaScript разработчик
Модули и сборка JavaScript
Моя история. С чего я начинал и к чему пришел…
cat **/*.js > build.js!
5
Файлы и cat **/*.js > build.js
• Это быстро и просто • Что плохого
– Собирается все без разбора – Возможны конфликты имен переменных – Результат плохо сжимается – Нужно учитывать порядок
Так жить нельзя! – Нужны модули.
7
Мне понадобились модули. Зачем?
• Разделение логических частей • Управление импортом/экспортом • Явные зависимости и их контроль • Меньше конфликтов переменных
Модуль? – нет, не слышал!
Learning JavaScript Design Patterns
http://clck.ru/8aLgX
include('main.js');!
10
(function ($) { var myStuff = {}; window.stuff = myStuff; })(jQuery);
IIFE и include()
11
include('common.js'); include('ru.js'); include('main.js');
IIFE и include(): Сборка
includify main.js > build.js
12
IIFE и include()
• Что хорошего – Модули в замыканиях – Можно наследовать сборки
• Что плохого – RegExp – Дублирование модулей
Я встретил её…
REQUIRE JS
15
RequireJS
• AMD • Асинхронные зависимости • Плагины • Оптимизация – r.js • Большое комьюнити
16
define(['jQuery', 'lodash'], function ($, _) { var myStuff = {}; return myStuff; });
RequireJS & AMD: Модули
17
<script data-main="js/app" src="js/require.js"> </script>
RequireJS & AMD: Сборка
node r.js -o build.js
IREQUIRE JS
Я думал, что это навсегда…
19
define(function () { var myStuff = {}; return myStuff; });
Много церемоний с define()
1. Нужно писать обертку
20
define("dojo/_base/html", [ "./kernel", "../dom", "../dom-style", "../dom-attr", "../dom-prop", "../dom-class", "../dom-construct", "../dom-geometry" ], function (dojo, dom, style, attr, prop, cls, ctr, geom) { });
Много церемоний с define()
2. Куча зависимостей – ад
http://clck.ru/4b7ew
22
define(function () { var myStuff = {}; return myStuff; });
Много церемоний с define()
3. Артефакты: Приходится табулировать
23
require('module'); // js? require('async!data', cb); // ? require(ComicSans); // font?
require() - God Object?
1. Возвращает что угодно, как угодно 2. Не сразу понятен результат
AMD и CJS
25
И еще AMD
• Приходится поддерживать AMD – jQuery, underscore, backbone, … – 2 версии с AMD и без
• Пытаются заразить Node.js – node-requirejs – в node и так есть модульная система
http://clck.ru/4b7dE
Сейчас мы друзья
Другие пути
28
Другие пути
• browserify – CommonJS – хорошо – слишком много от Node.js – плохо
• просто загрузчик – headjs – yepnopejs
29
Из моего опыта
• Сегодня все собирается. Даже dev • Читаемость кода очень важна
– Нужно исключить неявные конструкции
• Сборок бывает много – dev, production, dev-ru, test-en_US
• Нужен контроль результата сборки – Проверка целостности – Подробная информация о сборке
Я создал новый инструмент
LMD – Lazy Module Declaration
LMD
Модули – CommonJS Остальное делает сборщик
33
var $ = require('$'), myStuff = {}; module.exports = myStuff;
Модули – CommonJS/Modules 1.0*
http://clck.ru/4b7gO
34
Профит
• Ненавязчивый формат – Нет лишней писанины – Единообразие вида модулей
• Обратная совместимость с Node.js – Без плагинов, регистрации и SMS
• Оберткой модулей занимается сборщик
35
{ "root": "../js", "output": "../index.js", "modules": { "main": "main.js", "i18n": "locale/ru.json" }, "css": true, "ie": false, "worker": true }
Конфиг сборки
http://clck.ru/4b7gq
Проблема: Много конфигов
37
{ "extends": "index.json", "output": "../index-en.js" "modules": { "i18n": "locale/en.json" } }
Операции над конфигами
1. Наследование конфигов
http://clck.ru/4b7j2
38
{ "modules": { "i18n": "locale/en.json" } }
Операции над конфигами
2. Миксины конфигов
lmd index+en \ –output=index-en.js
http://clck.ru/4b7pI
39
{ "root": "../js", "modules": { "main": "main.js" }, "depends": "*.lmd.json" }
Операции над конфигами
3. Зависимости модулей
main.lmd.json хранит зависимости main.js
http://clck.ru/4b7sw
40
Профит
• Минус – нужно писать конфиг • JSON можно легко реиспользовать • Количество конфигов сократилось • Меньше писать сборочных скриптов • Легче понять результат сборки
Явные плагины
Гибкие плагины
Очень гибкие плагины
44
{ "image": true, "promise": true, "cache": true, "stats": true }
Явный способ подключения плагинов
http://clck.ru/4b7t6
Сборщик проверит плагины
45
// javascript require('module'); // css require.css('path/to.css', callback); // image+promise require.image('path/img.png') .then(callback);
LMD require – не God Object
http://clck.ru/4b7tO
46
Профит
• require() делает одну работу • Результат require() стал предсказуемым • Код стало проще воспринимать
______ __ __ !/\ ___\ /\ \ /\ \ !\ \ \____ \ \ \____ \ \ \ ! \ \_____\ \ \_____\ \ \_\ ! \/_____/ \/_____/ \/_/ !
!
http://clck.ru/4dU-0!
$ lmd -c cfg.json\ ✘! -o result.js ✘!!$ lmd make cfg ✔!$ lmd make cfg+ru ✔!$ lmd info cfg ✔!$ lmd ✔! atch ! fg!⇥ ⇥ ! c!w!
LMD GUI
Встроенная аналитика
http://clck.ru/4b8My
Интеграция с Grunt.js
https://npmjs.org/package/grunt-lmd
52
Профит LMD
• Максимум автоматизации – Сборщик LMD – Аналитика
• Максимум явного кода – require.*()
• Минимум писанины – CommonJS – CLI & GUI
• Минимум копипаста – Операции над кофигами
https://github.com/azproduction/lmd
Lazy Module Declaration
http://lmdjs.org