42
Component Inspector Роман Дворнов Avito Москва, октябрь 2015

Component Inspector

Embed Size (px)

Citation preview

Page 1: Component Inspector

Component InspectorРоман Дворнов

AvitoМосква, октябрь 2015

Page 2: Component Inspector

Работаю в Avito

Делаю SPA

Автор basis.js

Я…

За любую движуху, кроме голодовки ;)

Page 3: Component Inspector

DEMO поговорим про боль

Page 4: Component Inspector

• Позволяет инспектировать компоненты, показывает их DOM фрагмент

• Может показывать фрагмент кода для разных значений (классов, методов, объектов)

• Позволяет по клику открывать редактор с нужным файлом с курсором на нужном месте

4

Component Inspector

Page 5: Component Inspector

!

• Не завязано на фреймворк/библиотеку

• Библиотеки могут расширять возможности и предоставлять дополнительную информацию

5

Более того

Page 6: Component Inspector

6

За пределами браузера

Браузер dev-server

Редактор

ФайлКоманда в терминале

Запрос на открытие файла

Инструментированный код + source maps

Page 7: Component Inspector

Части решения

7

• Инструментирование кода

• Runtime API

• Инспекция DOM дерева

• dev-сервер

Page 8: Component Inspector

Инструментирование

Page 9: Component Inspector

Инструментирование – дополнение кода другим кодом,

который делает что-то еще

9

Page 10: Component Inspector

10

Код КодAST (ESTree)

Парсинг

Трансформации (Babel)

Трансляция

Esprima

Делаем трансформацию кода правильно

Просто добавь свой плагин

Page 11: Component Inspector

Инструментирование делается плагином для Babel

11

github.com/restrry/babel-plugin-source-wrapper

Page 12: Component Inspector

Что делает плагин

12

var foo = $devinfo(function(a, b) { return a + b;}, { … });!

var obj = $devinfo({ foo: 1 }, { … });

var foo = function(a, b) { return a + b;};!

var obj = { foo: 1 };

Page 13: Component Inspector

Делается автоматическии только на этапе разработки

13

Page 14: Component Inspector

Runtime API

Page 15: Component Inspector

15

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Page 16: Component Inspector

16

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Используем WeakMap для хранения информации: - объекты как ключи - не трансформирует объекты - не создает утечек памяти

Page 17: Component Inspector

17

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Основная функция регистрации, "добавляет" информацию только если ее еще нет у объекта

Page 18: Component Inspector

18

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Получение информации, используется инструментами

Page 19: Component Inspector

19

var obj = {};!

$devinfo(obj, { data: 123 });!

console.log($devinfo.get(obj));// > { data: 123 }

Использование

Page 20: Component Inspector

Инспектирование DOM

Page 21: Component Inspector

• знать границу компонента, т.е. определять элемент-контейнер компонента (DOM узел)

• определять владельца компонента (view) по элементу-контейнеру (по DOM узлу)

21

Для инструмента нужно

Page 22: Component Inspector

• если у DOM узла есть свойство __view – значит это контейнер компонента

• в свойстве __view хранится ссылка на view

22

Решение в лоб

Но лучше использовать WeakMap (node ➝ view)

Page 23: Component Inspector

Крохотный патч для Backbone

23

!

var _setElement = Backbone.View.prototype._setElement;Backbone.View.prototype._setElement = function() { _setElement.apply(this, arguments); this.el.__view = this;};

Page 24: Component Inspector

Или с WeakMap

24

!

var map = new WeakMap();var _setElement = Backbone.View.prototype._setElement;Backbone.View.prototype._setElement = function() { _setElement.apply(this, arguments); map.add(this.el, this);};window.getBackboneViewByNode = function(el) { return map.get(el)};

Page 25: Component Inspector

Использование

Page 26: Component Inspector

basis.js

26

Работает из коробки (нужен basis.js 1.5)

Page 27: Component Inspector

component-inspector

27

github.com/lahmatiy/component-inspector

Другие фреймворки

npm install component-inspector --save-dev

Page 28: Component Inspector

React

28

Подключение в html перед React!

<script src="node_modules/component-inspector/dist/react.js">

</script>

<script src="react.js"></script>

Page 29: Component Inspector

Backbone

29

Подключение в html после Backbone<script src="backbone.js"></script>

<script src="node_modules/component-inspector/dist/backbone.js">

</script>

Page 30: Component Inspector

Свое решение? Запросто!

30

Page 31: Component Inspector

31

<script src="node_modules/component-inspector/dist/base.js"></script>

Инициализация<script> initComponentInspector({ isComponentRootNode: function(node){ return Boolean(node && node.__view); }, getInstanceByNode: function(node){ if (node) { return node.__view; } } });</script>

Page 32: Component Inspector

32

<script src="node_modules/component-inspector/dist/base.js"></script>

Описываем API<script> initComponentInspector({ isComponentRootNode: function(node){ return Boolean(node && node.__view); }, getInstanceByNode: function(node){ if (node) { return node.__view; } } });</script>

Page 33: Component Inspector

Можно определить многое

33

• isComponentRootNode(node) • getComponentNameByNode(node) • getInstanceByNode(node) • getInstanceRootNode(instance) • getInstanceClass(instance) • getInstanceLocation(instance) • ...

github.com/lahmatiy/component-inspector#api-free-build

Page 34: Component Inspector

dev-сервер

Page 35: Component Inspector

• отдавать инструментированный код

• при отдаче html встраивать в него runtime.js

• исполнять команды, например, открытие файла в редакторе

35

dev-сервер долженв идеале

Page 36: Component Inspector

36

Вариант настройки: webpackИнструментирование webpack + babel + babel-plugin-source-wrapper !

Открытие файла в редакторе express или webpack-dev-server + express-open-in-editor

Page 37: Component Inspector

37

Пример конфигурации для Webpack + React

tinyurl.com/pwj6bln

Page 38: Component Inspector

Вариант настройки: basisjs-tools

38

> npm install basisjs-tools -g> npm install basisjs-tools-instrumenter// создать конфиг basis.config> basis server

{ "plugins": [ "basisjs-tools-instrumenter" ] }

Сервер будет отдавать инструментированный код и встраивать необходимое в html

Page 39: Component Inspector

• open-in-editornpm пакет для программного открытия файла в редакторе github.com/lahmatiy/open-in-editor

• express-open-in-editor расширение для Express для открытия файла по урлу github.com/lahmatiy/express-open-in-editor

• extract-code-fragment получение раскрашенного фрагмента кода из файла скоро

39

Побочные продукты

Page 40: Component Inspector

Главное – идея

Page 41: Component Inspector

Попробуйте – это круто! ;)

Page 42: Component Inspector

Вопросы?

42

Роман Дворнов @rdvornov [email protected] github.com/lahmatiy

tinyurl.com/moscowjs-ciComponent Inspector

basis.js github.com/basisjs