SPA инструменты
Роман Дворнов
Avito
SPA Meetup, февраль 2015
О себе
• Работаю в Avito
• Делаю SPA
• Автор basis.js
2
Все непросто…
3
Веб сегодня – 

большой мир возможностей...
4
Бла-бла-бла…
5
Программирование абстрактно,
нужно многое держать в голове –
легко упустить детали
6
Нам нужны помощники –
инструменты, которые помогут
нам больше видеть и понимать
7
Сложность(кол-воболи)
Размер проекта (в попугаях)
Все делаем сами
8
Сложность(кол-воболи)
Размер проекта (в попугаях)
Все делаем сами
Используем инструменты
9
Инструменты
10
Типы инструментов
• среда разработки – редаторы, IDE + плагины
• консольные – командная строка
• браузерные – in-app и плагины
11
Среда разработки
• Нам "не повезло" – веб-технологии слишком гибкие
• либо базовые вещи – мало подсказок
• либо все подряд – слишком много подсказок
• обламываемся, если CommonJS, ES6 modules…
• обламываемся, если среда не знает "фреймворк"
12
Консольные инструменты
• Расцвет эпохи Task Runner'ов (node.js, io.js)
• "сборка" - конкатенация, пре-/пост-
процессоры, ...
• FS watch – live reload, пересборка, ...
• запуск тестов, линтеры, валидаторы
• …
13
Браузерные инструменты
• браузерные "Developer Tools"
• простые утилитарные плагины
• плагины фреймворков (React, Ember, Basis.js)
• runtime приложения
14
Что делать, если существующих
инструментов не хватает?
15
Создать свои!
16
Лучше день потерять,
потом за 5 минут
долететь…
Главное видеть проблемы 

и стараться решать их
18
Какого типа инструменты
делать?
19
В идеале – все три
20
Среда разработки
Консольные инструменты
Браузерные решения
+
+
Сборка
21
Консольный инструмент
Обычная практика
• находим файлы по маске
• прогоняем через пре-/пост-процессоры
• объединяем, минизируем
• ...
• PROFIT!
22
Плюсы и минусы
+ достаточно просто
– разные типы контента обрабатываются независимо
– файлы попадают в сборку, без разбора
используются или нет
– каждое изменение файла – пересборка
23
А как по другому?
24
В идеале сборщик 

должен понять, что мы хотели 

и сделать из этого 

оптимальную сборку
25
Сценарий
• указываем html-файл (у нас же single page!)
• он находит используемые файлы
• прогоняет через пре-/пост-процессоры и т.д.
• объединяет, перестраивает, перелинковывает контент
• ...
• PROFIT!
26
Плюсы и минусы
+ не нужно объяснять лишнего сборщику
+ в сборку попадается только нужное
– несколько сложнее реализация сборщика
– менее надежно (не пишите непонятного ;)
27
DEMO
28
Ключевой компонент –
профиль приложения
29
Профиль приложения
• граф зависимостей – в частном случае
файлы и их связи
• факты о контенте – что и где используется
30
Как собрать профиль?
• для этого сборщик должен быть немного
"браузером" :)
• разобрать контент "файлов"
• найти и интерпритировать конструкции
• собрать информацию воедино
31
Разбор полетов
32
контента
AST: туда и обратно
Способы работы с контентом
• Как со строкой – Regular Expressions
• Структурированное представление – AST*
33
* Abstract Syntax Tree
RegExp
+ дешевое решение для простых задач
– под каждую задачу свой RegExp
– ненадежно
– трудно поддерживать и расширять
– почти невозможно делать сложные вещи
34
AST
+ надежно
+ универсальное решение
+ гораздо проще поддерживать
+ возможность выполнять задачи любой сложности
– более дорогое решение для простых задач
– можно потерять часть информации (формат и т.д.)
35
Наш выбор – AST
36
Пример
37
ASTCSS
[ "stylesheet", [	
"atrules",	
[	
"atkeyword",	
[ "ident", "import" ]	
],	
[ "s", " " ],	
[ "string", "'path/to/file.css'" ]	
]	
]
@import 'path/to/file.css';
gonzales (csso)
Пример
38
ASTJavaScript
[ "toplevel", [	
[ "var", [	
[ "module",	
[ "call",	
[ "name", "require" ],	
[ [ "string", "module" ] ]	
]	
]	
] ]	
] ]
var module = require('module');
uglifyjs 1.x
Пример
39
ASTJavaScript
{ "type": "Program",	
"body": [ {	
"type": "VariableDeclaration",	
"declarations": [ {	
"type": "VariableDeclarator",	
"id": {	
"type": "Identifier",	
"name": "module"	
},	
...
var module = require('module');
ESTree (Esprima, uglifyjs 2.x, …)
Все уже придумано до нас
• JavaScript – Esprima, acorn, uglifyjs, …
• CSS – gonzales (csso), postCSS, …
• (X)HTML, XML – htmlparser2, sax, …
40
Для многих форматов есть парсеры, производящие AST
Работаем с AST
• walker – делает рекурсивный обход дерева
• анализ

= walker + сбор фактов
• трансформер (transformer)

= walker + модифицикация дерева
• транслятор (translator)

= walker + генерация кода (строка)
41
Пример walker'а
42
function gonzalesAstWalker(ast, handlers){	
function walk(token){	
for (var i = 2, child; child = token[i]; i++) {	
var handler = handlers[child[1]];	
if (typeof handler == 'function')	
handler(child);	
walk(child);	
}	
}	
!
walk([{}, '', ast]);	
};	
для AST производимого gonzales
Используем
43
var ast = gonzales.parse(	
'.foo { background: url("foo.jpg"); }' +	
'.bar { background: url("bar.png"); }',	
'stylesheet', true	
);	
!
gonzalesAstWalker(ast, {	
'uri': function(token){	
console.log(token[2][2]);	
}	
});
находим все url(…)
Вывод в консоли:
"foo.jpg"	
"bar.png"
Поиск Священного Грааля
44
связей
HTML
• <script src="{url}"></script>	
• <script>{inlineScript}</script>	
• <link rel="stylesheet" href="{url}">	
• <style>{inlineStyle}</style>	
• <img src="{url}">	
• <element style="{inlineStyleBlock}">	
• ...
45
CSS
• @import {url}	
• url({url})
46
CSS
• @import {url}	
• url({url})
46
Вы уже знаете как это сделать ;)
JavaScript
47
Все несколько сложнее…
Нужно несколько проходов

и больше телодвижений
JavaScript проход №1
• определяем области видимости
• для определенных значений добавляем
обработчики:

48
var fnToken = someScope.get('require');	
fnToken.run = function(token, args){	
// интерпритация функции для сборщика	
};
JavaScript проход №2
• делаем базовую интерпритацию
• объявления, присвоения
• вызов функций
• return
• стараемся понять, что можем понять
49
Примерно вот так
50
jsAstWalker(ast, {	
'call': function(token, scope){	
var expr = token[1];	
var args = token[2];	
var fn = scope.resolve(expr);	
!
if (fn && fn[0] == 'function' && fn.run)	
fn.run(token, args.map(function(a){	
return scope.resolve(a) || a;	
}));	
},	
...	
});	
обработка вызовов
функций
Успешно понимаем
51
var foo = basis.require;	
foo('./path/to/file.ext');	
// и даже так	
var prefix = './path/to';	
var bar = foo;	
bar(prefix + '/foo.ext');
на примере basisjs-tools
сборщик правильно
распознает вызов
basis.require и
значения аргументов
Так просто не обманешь
52
function example(){	
var basis = {	
require: function(){ … }	
};	
basis.require('module');	
}
на примере basisjs-tools
Этот вызов будет
проигнорирован, 

т.к. функция не
оригинальная
Да, понимает не все
53
var require = basis.require;	
var modules = ['foo', 'bar'];	
modules.forEach(function(name){	
require(name);	
});
на примере basisjs-tools
сборщик распознает
вызов basis.require, но
не сможет разрешить
названия модулей
Можно упороться и научить
сборщик понимать более
сложные патерны
54
С другой стороны это "фича",
которая останавливает от
написания "странного" кода ;)
55
Профиль приложения 

полезен не только для сборки
56
Профиль приложения
• Профиль + трансформации = сборка
• Профиль + проверки = линтер
• Профиль + … = …
57
Главное: знаем все связи 

и можно работать со всеми
видами контента одновременно
58
DEMO
59
Матчинг CSS классов
• Сохраняем карту – какие классы используются
в HTML (шаблонах)
• Сохраняем карту – какие классы используются
в селекторах
• Есть в HTML, но нет в CSS –> варнинг
• Есть в CSS, но нет в HTML –> варнинг
60
Делаем свой линтер
61
Делаем свой линтер
• Пишем консольную утилиту, которая
выводит список ошибок и файлов 

с местоположением ошибки
• Интегрируем с редактором
62
Это очень важно
Интеграция с Sublime Text
63
from SublimeLinter.lint import NodeLinter, util	
!
class Basisjs(NodeLinter):	
syntax = ('javascript', 'javascriptnext', 'html', 'css', 'json')	
cmd = ('basis', 'lint', '@', '-r', 'checkstyle')	
regex = (	
r'^s+?<error line="(?P<line>d+)" '	
r'column="(?P<col>d+)" '	
r'severity="(?P<warning>error)" '	
r'message="(?P<message>.+?)"'	
)	
multiline = True	
tempfile_suffix = '-'
плагин для SublimeLinter
Вызываем
консольную
утилиту
PROFIT!
64
Стыкуем все вместе
65
DEMO
66
67
Плагин
Браузер Dev-сервер
Среда
разработки
Web Socket (socket.io) Файловая система
DOM события
Немного деталей
• Сервер слушает файловую систему, и
отправляет браузеру уведомления об
изменениях
• Браузер отправляет серверу команды и
слушает уведомления
68
Открытие файла в редакторе
• Браузер отправляет команду dev-серверу

openFile('path/to/file.ext:10:20')
• dev-сервер выполняет консольную команду

subl path/to/file.ext:10:20
69
Кое-что еще…
70
DEMO
71
Под капотом все то же: 

парсер, AST, walker'ы, …
72
И еще немного магии
• Dev-режим
• Компонентный подход
• DOM шаблонизация
• Разделение логики и представления
• Модульность
• Sandbox
• …
73
В заключении
74
Если чего-то не хватает –
делайте это сами!
75
Наша эффективность зависит
от инструментов, не меньше чем
от фреймворков и нашего опыта
76
Главное видеть проблемы 

и стараться решать их
77
Спасибо!
78
Роман Дворнов
@rdvornov
rdvornov@gmail.com
basis.js
basisjs.com
github.com/basisjs

More Related Content

PDF
Опыт разработки эффективного SPA
PDF
Инструменты разные нужны, инструменты разные важны
PDF
Жизнь в изоляции
PDF
Баба Яга против!
PDF
Инструментируй это
PDF
Не бойся, это всего лишь данные... просто их много
PDF
Быстро о быстром
PDF
Basis.js – «под капотом»
Опыт разработки эффективного SPA
Инструменты разные нужны, инструменты разные важны
Жизнь в изоляции
Баба Яга против!
Инструментируй это
Не бойся, это всего лишь данные... просто их много
Быстро о быстром
Basis.js – «под капотом»

What's hot (20)

PDF
DOM-шаблонизаторы – не только "быстро"
PDF
Unit-тестирование скриншотами: преодолеваем звуковой барьер
PDF
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
PDF
Kranonit s16 (python). dmitry furzenko
PDF
Компонентный подход: скучно, неинтересно, бесперспективно
PDF
basis.js - почему я не бросил разрабатывать свой фреймворк
PDF
Инструменты разные нужны, инструменты разные важны
PDF
Как построить DOM
PDF
Изоморфный JavaScript — будущее уже здесь
PDF
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
PPT
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
PPTX
Ruby - или зачем мне еще один язык программирования?
PPTX
Chef @DevWeb
PDF
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
PDF
JavaScript Базовый. Занятие 07.
PDF
Как сделать ваш JavaScript быстрее
PDF
МРТ для данных, Frontend Conf 2016
PPTX
Читабельные отчеты для автоматизации на C# / Gallio / BDDfy
PDF
«Организация Frontend-разработки на крупном проекте» — Дмитрий Кузнецов
PDF
Внутреннее устройство и оптимизация бандла webpack
DOM-шаблонизаторы – не только "быстро"
Unit-тестирование скриншотами: преодолеваем звуковой барьер
Basis.js - почему я не бросил разрабатывать свой фреймворк (extended)
Kranonit s16 (python). dmitry furzenko
Компонентный подход: скучно, неинтересно, бесперспективно
basis.js - почему я не бросил разрабатывать свой фреймворк
Инструменты разные нужны, инструменты разные важны
Как построить DOM
Изоморфный JavaScript — будущее уже здесь
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
Ruby - или зачем мне еще один язык программирования?
Chef @DevWeb
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
JavaScript Базовый. Занятие 07.
Как сделать ваш JavaScript быстрее
МРТ для данных, Frontend Conf 2016
Читабельные отчеты для автоматизации на C# / Gallio / BDDfy
«Организация Frontend-разработки на крупном проекте» — Дмитрий Кузнецов
Внутреннее устройство и оптимизация бандла webpack
Ad

Viewers also liked (20)

PDF
CSS parsing: performance tips & tricks
PDF
CSSO – compress CSS (english version)
PDF
Парсим CSS
PDF
Парсим CSS: performance tips & tricks
PDF
SphinxSearch Meetup - Tips&tricks
PDF
CSSO – история ускорения
PDF
CSSO — минимизируем CSS
PPT
Clearing hurdles
PDF
Experiment Prototyping
PPTX
Ускоряем исследования с помощью конкурсов как их готовить и выигрывать / Иван...
PDF
Bezier curves
PPTX
Avito iab1502 olga ky
PDF
AVITO. Решаем проблемы по мере их поступления. Стачка 2013
PPSX
Agile — это не то, что ты думаешь
PDF
Карточный домик
PDF
Remote (dev)tools своими руками
PPTX
Avito usage of_data_in_media_campaigns_olga_ky
PPSX
Agile по Суворову
PDF
Чем полезен PMBOK для Agile-менеджера
PDF
Максим Савельев, 2ГИС: "Точки контакта с аудиторией. Секреты рекламы, которые...
CSS parsing: performance tips & tricks
CSSO – compress CSS (english version)
Парсим CSS
Парсим CSS: performance tips & tricks
SphinxSearch Meetup - Tips&tricks
CSSO – история ускорения
CSSO — минимизируем CSS
Clearing hurdles
Experiment Prototyping
Ускоряем исследования с помощью конкурсов как их готовить и выигрывать / Иван...
Bezier curves
Avito iab1502 olga ky
AVITO. Решаем проблемы по мере их поступления. Стачка 2013
Agile — это не то, что ты думаешь
Карточный домик
Remote (dev)tools своими руками
Avito usage of_data_in_media_campaigns_olga_ky
Agile по Суворову
Чем полезен PMBOK для Agile-менеджера
Максим Савельев, 2ГИС: "Точки контакта с аудиторией. Секреты рекламы, которые...
Ad

Similar to SPA инструменты (20)

PDF
DevOps в Agile среде. Как, почему и когда инструменты помогают.
PPTX
Little Service in 2h
PDF
"Девопс - это не только для программистов. Практические примеры из жизни одно...
PDF
PPTX
Программирование как способ выражения мыслей.
PPTX
Построение собственного JS SDK — зачем и как?
PDF
UWDC 2013, Как мы используем Yii
PPT
HSE{Consult}: DevOps – новая методология разработки
PDF
D2D Pizza JS Илья Беда "Куда мы все катимся?"
PPTX
2014.12.23 Александр Андреев, Parallels
PPTX
Практика эксплуатации уязвимостей в прикладных программах
PDF
Вадим Макишвили "Вёрстка в IntelliJIDEA"
PPTX
Информационная безопасность в веб - основы
PDF
И снова разработка под iOS. Павел Тайкало
PDF
«DevOps — это о передаче смысла» — Александр Титов, Express 42
PDF
DevOps или исскуство ухода за Интернет-проектом
ODP
About Python
PPTX
20 апреля, DEV {highload}, "Демоны в большом проекте – проблемы и их решения ...
PPTX
PowerShell
PPTX
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
DevOps в Agile среде. Как, почему и когда инструменты помогают.
Little Service in 2h
"Девопс - это не только для программистов. Практические примеры из жизни одно...
Программирование как способ выражения мыслей.
Построение собственного JS SDK — зачем и как?
UWDC 2013, Как мы используем Yii
HSE{Consult}: DevOps – новая методология разработки
D2D Pizza JS Илья Беда "Куда мы все катимся?"
2014.12.23 Александр Андреев, Parallels
Практика эксплуатации уязвимостей в прикладных программах
Вадим Макишвили "Вёрстка в IntelliJIDEA"
Информационная безопасность в веб - основы
И снова разработка под iOS. Павел Тайкало
«DevOps — это о передаче смысла» — Александр Титов, Express 42
DevOps или исскуство ухода за Интернет-проектом
About Python
20 апреля, DEV {highload}, "Демоны в большом проекте – проблемы и их решения ...
PowerShell
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков

More from Roman Dvornov (6)

PDF
Масштабируемая архитектура фронтенда
PDF
CSS глазами машин
PDF
My Open Source (Sept 2017)
PDF
Rempl – крутая платформа для крутых инструментов
PDF
CSSO — сжимаем CSS (часть 2)
PDF
Component Inspector
Масштабируемая архитектура фронтенда
CSS глазами машин
My Open Source (Sept 2017)
Rempl – крутая платформа для крутых инструментов
CSSO — сжимаем CSS (часть 2)
Component Inspector

SPA инструменты