164
Жизнь в изоляции Роман Дворнов Avito Санкт-Петербург 2015

Жизнь в изоляции

  • Upload
    basisjs

  • View
    1.282

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Жизнь в изоляции

Жизнь в изоляцииРоман Дворнов

Avito

Санкт-Петербург 2015

Page 2: Жизнь в изоляции

Работаю в Avito

Делаю SPA

Автор basis.js

Я…

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

Page 3: Жизнь в изоляции

Проблема

Page 4: Жизнь в изоляции

Большие сайты и SPA

4

Page 5: Жизнь в изоляции

5

Мамонта нужно есть по частям…

Page 6: Жизнь в изоляции

Компонентный подход и модульность – возможность решать большую проблему

порционно

6

Page 7: Жизнь в изоляции

Основная задача: избежать конфликтов

7

Page 8: Жизнь в изоляции

Инкапсуляция

8

«обеспечение доступности главного … путем помещения всего мешающего, второстепенного

в некую условную капсулу (чёрный ящик)»

ru.wikipedia.org/wiki/Инкапсуляция

Page 9: Жизнь в изоляции

Способы инкапсуляции

9

Page 10: Жизнь в изоляции

Способы инкапсуляции

• Скрипты – замыкания, модули (ES6)

9

Page 11: Жизнь в изоляции

Способы инкапсуляции

• Скрипты – замыкания, модули (ES6)

• Разметка – неймспейсы (например, SVG)

9

Page 12: Жизнь в изоляции

Способы инкапсуляции

• Скрипты – замыкания, модули (ES6)

• Разметка – неймспейсы (например, SVG)

• Стили – ???

9

Page 13: Жизнь в изоляции

Изоляция стилей

Page 14: Жизнь в изоляции

4 подхода11

Page 15: Жизнь в изоляции

СоглашениеПодход №1

Page 16: Жизнь в изоляции

Некоторая договоренность, описывающая принцип именования классов

13

Page 17: Жизнь в изоляции

блок__элемент--модификатор

14

Например

Это БЭМ, но все далее так же справедливои для OOCSS, SMACSS, SUIT, ACSS и т.д.

Page 18: Жизнь в изоляции

Изоляция достигается путем придумывания уникальных имен

15

Page 19: Жизнь в изоляции

«Есть только две трудные задачи в области информатики: инвалидация кеша и придумывание названий.»

16

– Фил Карлтон

Page 20: Жизнь в изоляции

17

Знаешь сколько верстальщики тратят на придумывание одного имени класса?

Целый день. Целый день, Карл!

Page 21: Жизнь в изоляции

Это не проблема, когда мало уникальных компонент

18

Page 22: Жизнь в изоляции

Универсальный компонент v.s.

Компонент под задачу

19

Page 23: Жизнь в изоляции

20

Page 24: Жизнь в изоляции

21

<div class="app-bookings-change-status-popup-option app-bookings-change-status-popup-option_{disabled} app-bookings-change-status-popup-option_{hidden}"> <span class="app-bookings-change-status-popup-option__caption app-bookings-change-status-popup-option__caption_{selected}"> {title} </span></div>

Проблема, когда уникальных компонент много

Реальный пример из жизни

Page 25: Жизнь в изоляции

Другие проблемы• Уникальность обеспечивается человеком

• Сложность автоматизированного анализа

• Нет механизмов интеграции сторонней верстки в свою или свою в чужое окружение

• …22

Page 26: Жизнь в изоляции

Основная проблема – человеческий фактор

23

Page 27: Жизнь в изоляции

Если правило можно нарушить – оно будет нарушено

24

Page 28: Жизнь в изоляции

Нельзя проверить правильно ли вы делаете, это может сказать

только человек

25

Привет, субъективное мнение!

Page 29: Жизнь в изоляции

Плюсы• Хоть какая-то система

• Дешево для внедрения

26

Page 30: Жизнь в изоляции

Не смотря на популярность –так себе решение*

27

* для сложных проектов

Page 31: Жизнь в изоляции

ТехнологияПодход №2

Page 32: Жизнь в изоляции

Shadow DOM

29

часть Web Components

w3c.github.io/webcomponents/spec/shadow/

Page 33: Жизнь в изоляции

Shadow DOM – возможность инкапсулировать

DOM-фрагмент

30

Page 34: Жизнь в изоляции

31

Все созданные ранее API не видят содержимое Shadow Tree

Page 35: Жизнь в изоляции

32

А там может быть любая разметка и стили к ней

Page 36: Жизнь в изоляции

Любая вложенность

Page 37: Жизнь в изоляции

Любая вложенность

Page 38: Жизнь в изоляции

Shadow DOM – это всегда JavaScript

34

Page 39: Жизнь в изоляции

35

function init(container) { var shadowRoot = container.createShadowRoot();!

var content = document.createElement('div'); content.innerHTML = 'some markup';!

var styles = document.createElement('style'); styles.textContent = '/* some css */';!

shadowRoot.appendChild(styles); shadowRoot.appendChild(content);}

Создаем корень Shadow Tree

Page 40: Жизнь в изоляции

36

function init(container) { var shadowRoot = container.createShadowRoot();!

var content = document.createElement('div'); content.innerHTML = 'some markup';!

var styles = document.createElement('style'); styles.textContent = '/* some css */';!

shadowRoot.appendChild(styles); shadowRoot.appendChild(content);}

Создаем DOM фрагмент

Page 41: Жизнь в изоляции

37

function init(container) { var shadowRoot = container.createShadowRoot();!

var content = document.createElement('div'); content.innerHTML = 'some markup';!

var styles = document.createElement('style'); styles.textContent = '/* some css */';!

shadowRoot.appendChild(styles); shadowRoot.appendChild(content);}

Создаем стили

Page 42: Жизнь в изоляции

38

function init(container) { var shadowRoot = container.createShadowRoot();!

var content = document.createElement('div'); content.innerHTML = 'some markup';!

var styles = document.createElement('style'); styles.textContent = '/* some css */';!

shadowRoot.appendChild(styles); shadowRoot.appendChild(content);}

Вставляем все в Shadow Tree

Page 43: Жизнь в изоляции

Custom Elements позволяют абстрагироваться от нюансов

реализации

39

www.w3.org/TR/custom-elements/

Для них также нужен JavaScript

Page 44: Жизнь в изоляции

Проблема изоляции решена?

40

Page 45: Жизнь в изоляции

Миф:

Shadow DOM обеспечивает полную изоляцию стилей

41

На текущий момент

Page 46: Жизнь в изоляции

А Shadow DOM-то – протекает• Часть стилей наследуется от хоста

font, line-height, color и т.д.

• Можно стилизовать извне, используя комбинатор >>> (бывш. /deep/ и ^^)

42

dev.w3.org/csswg/css-scoping/

Page 47: Жизнь в изоляции

43

Page 48: Жизнь в изоляции

Хорошая новость: Все производители браузеров

намерены внедрять Shadow DOM

44

встреча Google, Mozilla, Apple и Microsoft

Page 49: Жизнь в изоляции

45

Но текущий дизайн «не очень»…

Page 50: Жизнь в изоляции

Надо «все» переделать• Будет два режима open (то что сейчас) и close (более закрытый)

• Отказ от комбинатора >>> (м.б. будут слоты)

• Потребуется переделать текущий API

• ...

46

tinyurl.com/oqkv5u6

Page 51: Жизнь в изоляции

Плюсы

• Честная изоляция (особенно в режиме close)

• Браузерное решение (возможный стандарт)

47

Page 52: Жизнь в изоляции

Минусы• Сложная концепция

• Требуется JavaScript

• Трудно полифилить

• Спецификация далека от завершения, все еще поменяется

48

Page 53: Жизнь в изоляции

Пока рано использовать, нужно еще подумать…

49

Page 54: Жизнь в изоляции

Инлайн-стилиПодход №3

Page 55: Жизнь в изоляции

Предложение от команды React – пишем CSS в JavaScript

51

speakerdeck.com/vjeux/react-css-in-jsspeakerdeck.com/vjeux/react-css-in-js-react-france-meetup

Page 56: Жизнь в изоляции

52

var React = require('react');!

var styles = { button: { color: 'white', backgroundColor: 'red' }};!

var MyButton = React.createClass({ render: function() { return <button style={styles.button}>Hello, world!</button> }});

Page 57: Жизнь в изоляции

А как же каскад, псевдоклассы,

медиавыражения и т.д.?

53

Page 58: Жизнь в изоляции

54

function merge(...args){ return Object.assign({}, ...args);}!

var styles = { // ... disabled: { opacity: .5 }};!

<button style={merge( styles.button, condition && styles.disabled)}>Hello, world!</button>

Каскад

.button { ...}!

.disabled { opacity: .5;}

Page 59: Жизнь в изоляции

55

.button { background-color: gray;}.button:hover { background-color: red;}!

<button onMouseEnter={function(){ this.setState({ hover: true }); }} onMouseLeave={function(){ this.setState({ hover: false }); }} style={{ background: this.state.hover ? 'red' : 'gray' }}> Hello, world!</button>

:hover

Page 60: Жизнь в изоляции

56

.button { width: 600px;}@media (max-device-width: 1024px) { .button { width: 300px; }}!

<button style={{ width: window.innerWidth > 1024 ? 600 : 300 }}> Hello, world!</button>

Media Queries

+ обработчик на window.resize

Page 61: Жизнь в изоляции

57

Реакция здорового человека

Page 62: Жизнь в изоляции

Они убили Кенни лучшее в CSS

58

Page 63: Жизнь в изоляции

Плюсы• Изолированные стили без селекторов

• Все возможности JavaScript для стилей

• Нет проблемы специфичности

59

Page 64: Жизнь в изоляции

Минусы• Подходит только для решений в стиле React

• Полное слияние логики и представления

• Нельзя использовать пре- и пост-процессоры

• Нельзя применять анализ и оптимизировать

• Бесполезность браузерных Developer Tools60

Page 65: Жизнь в изоляции

61

Шурик, Вы комсомолец? Это же не наш метод! Где гуманизм?

Page 66: Жизнь в изоляции

ПроцессингПодход №4

Page 67: Жизнь в изоляции

Пре- и пост-процессоры: транспиляция, трансформация, оптимизация, минификация…

63

Скрипты Разметка Стили

Page 68: Жизнь в изоляции

«Проблема»: процессоры рассматриваются в рамках одной технологии

64

Page 69: Жизнь в изоляции

Но если работать с технологиями совместно, можно получить больше

65

Page 70: Жизнь в изоляции

Рассмотрим

Basis

Ember

React

66

Page 71: Жизнь в изоляции

BasisПодход №4.1

Page 72: Жизнь в изоляции

DOM-шаблонизаторы – не только «быстро»

68

tinyurl.com/domtemplates

Год назад в докладе

Page 73: Жизнь в изоляции

Тогда была только идея, теперь есть реализация и опыт

69

Page 74: Жизнь в изоляции

Предусловия

• В JavaScript не используем CSS-классы(абстрагируемся от верстки)

• В шаблонах явно указываются используемые файлы стилей (нет глобальных)

70

Page 75: Жизнь в изоляции

71

<b:style src="block.css"/><div class="block block_{hidden}"> {caption}</div>

.block { … }

.block_hidden { … }

block.css

block.tmpl

Вот так

Инструкция шаблонизатору о необходимости подключить файл стилей

Префикс b: (сокр. от basis) стандартный механизм неймспейсов в XML (для избежания конфликта имен)

Page 76: Жизнь в изоляции

Взяв любой шаблон, мы «знаем» всю его разметку и используемые им стили

72

Page 77: Жизнь в изоляции

Изоляция включается инструкцией шаблонизатору

<b:isolate/>

73

Page 78: Жизнь в изоляции

Изоляция достигается путем добавления уникального

префикса всем именам классов

74

Page 79: Жизнь в изоляции

75

<b:style src="block.css"/><b:isolate/><div class="block block_{hidden}"> {caption}</div>

.block { … }

.block_hidden { … }

block.css

block.tmpl

Добавляем инструкцию

Page 80: Жизнь в изоляции

76

<b:style src="block.css"/><b:isolate/><div class="block block_{hidden}"> {caption}</div>

.block { … }

.block_hidden { … }

block.css

block.tmpl

Отдаем шаблонизатору

!!

Шаблонизатор

Пре-процессор

Page 81: Жизнь в изоляции

77

Шаблонизатор преобразует разметку и стили

<b:style src="block.css"/><b:isolate/><div class="block block_{hidden}"> {caption}</div>

.block { … }

.block_hidden { … }

block.css

block.tmpl

!!

Шаблонизатор

Пре-процессор

Page 82: Жизнь в изоляции

77

Шаблонизатор преобразует разметку и стили

<link href="block.css?prefix=jc1hsy_">!

<div class="jc1hsy_block jc1hsy_block_{hidden}"> {caption}</div>

.jc1hsy_block { … }

.jc1hsy_block_hidden { … }

block.css?prefix=jc1hsy_

Разметка

!!

Шаблонизатор

Пре-процессор

Page 83: Жизнь в изоляции

Префиксы генерируются случайным образом, вид зависит от задачи

78

Еще вернемся к этому

Page 84: Жизнь в изоляции

Непредсказуемость префикса лишает возможности «хакать»

верстку извне

79

Честный АНБ – без вариантов

Page 85: Жизнь в изоляции

80

<div class="app-bookings-change-status-popup-option app-bookings-change-status-popup-option_{disabled} app-bookings-change-status-popup-option_{hidden}"> <span class="app-bookings-change-status-popup-option__caption app-bookings-change-status-popup-option__caption_{selected}"> {title} </span></div>

Помните пример?

Page 86: Жизнь в изоляции

81

<b:style src="option.css"/><b:isolate/>!

<div class="option option_{disabled} option_{hidden}"> <span class="caption caption_{selected}"> {title} </span></div>

То же с изоляцией

Page 87: Жизнь в изоляции

Фишка не только в префиксах…

82

Page 88: Жизнь в изоляции

Переопределение стилей вместо добавления

новых классов

83

Page 89: Жизнь в изоляции

84

Безопасное дополнение стилей

<b:style src="button.css"/><button class="button"> click me</button>

button.tmpl<b:isolate/><b:style> .button { background: green; }</b:style><b:include src="./button.tmpl"/>

ok-button.tmpl

<b:isolate/><b:style> .button { background: red; }</b:style><b:include src="./button.tmpl"/>

cancel-button.tmpl

Page 90: Жизнь в изоляции

85

Безопасное дополнение стилей<b:isolate/><b:style> .button { background: green; }</b:style><b:include src="./button.tmpl"/>

ok-button.tmpl

<b:isolate/><b:style> .button { background: red; }</b:style><b:include src="./button.tmpl"/>

cancel-button.tmpl

<b:style src="button.css"/><button class="button"> click me</button>

button.tmpl

Page 91: Жизнь в изоляции

85

Безопасное дополнение стилей<b:isolate/><b:style> .button { background: green; }</b:style><b:include src="./button.tmpl"/>

ok-button.tmpl

<b:isolate/><b:style> .button { background: red; }</b:style><b:include src="./button.tmpl"/>

cancel-button.tmpl

<style> .jkc83s_button { … } .jkc83s_button { background: green; }</style><button class="jkc83s_button"> click me</button>

<style> .h9sg2n_button { … } .h9sg2n_button { background: green; }</style><button class="h9sg2n_button"> click me</button>

Page 92: Жизнь в изоляции

!

Стили раздельно для примера, в сборке все стили

объединяются и сжимаются86

Page 93: Жизнь в изоляции

Масштабируем подход: изоляция включаемой верстки

87

Page 94: Жизнь в изоляции

88

<b:isolate/><b:style> .example-foo { color: red; }</b:style><div class="panel"> <b:include src="foo.tmpl" isolate="example-"/> <b:include src="foo.tmpl" isolate> <b:style src="nested.css"/> </b:include></div>

example.tmpl<b:style src="foo.css"/><div class="foo"> example</div>

foo.tmpl

Можно указывать конкретный префикс для обращения вне включения, или не указывать и добавлять стили внутри инструкции включения

Изолируем включения

Page 95: Жизнь в изоляции

89

<link href="foo.css?prefix=hs83shyf_example-"><link href="foo.css?prefix=hs83shyf_y0dk7x_"><link href="nested.css?prefix=hs83shyf_y0dk7x_"><style> .hs83shyf_example-foo { color: red; }</style><div class="hs83shyf_panel"> <div class="hs83shyf_example-foo"> example </div> <div class="hs83shyf_y0dk7x_foo"> example </div></div>

Page 96: Жизнь в изоляции

90

<link href="foo.css?prefix=hs83shyf_example-"><link href="foo.css?prefix=hs83shyf_y0dk7x_"><link href="nested.css?prefix=hs83shyf_y0dk7x_"><style> .hs83shyf_example-foo { color: red; }</style><div class="hs83shyf_panel"> <div class="hs83shyf_example-foo"> example </div> <div class="hs83shyf_y0dk7x_foo"> example </div></div>

3 изолированные области имен в одной разметке!

Page 97: Жизнь в изоляции

CSS неймспейсы: изоляция файлов стилей

91

Page 98: Жизнь в изоляции

92

<b:style src="bootstrap.css" ns="bt"/><b:style src="icons.css" ns="icon"/><b:style src="style.css"/>!

<div class="active"> <span class="icon icon:active"></span> <button class="bt:btn bt:active"> Button </button></div>

Решаем проблему конфликта имен

Page 99: Жизнь в изоляции

93

<link href="bootstrap.css?prefix=iv7z2b_"><link href="icons.css?prefix=jasdhb_"><link href="style.css">!

<div class="active"> <span class="icon jasdhb_active"></span> <button class="iv7z2b_btn iv7z2b_active"> Button </button></div>

Имена из разных файлов стилей не пересекаются

Page 100: Жизнь в изоляции

94

<link href="bootstrap.css?prefix=iv7z2b_"><link href="icons.css?prefix=jasdhb_"><link href="style.css">!

<div class="active"> <span class="icon jasdhb_active"></span> <button class="iv7z2b_btn iv7z2b_active"> Button </button></div>

Знаем какой класс из какого файла

Page 101: Жизнь в изоляции

Кое что еще

95

Page 102: Жизнь в изоляции

Есть же еще есть пост-процессинг!

96

Page 103: Жизнь в изоляции

97

PostCSS множество плагинов

csso структурная оптимизация

Например

Page 104: Жизнь в изоляции

Оптимизации

98

Page 105: Жизнь в изоляции

99

.jkc83s_button { width: 100px; color: green;}

.jkc83s_button { color: red; width: 100px;}.jkc83s_button { color: green;}

csso

csso умеет объединять блоки с одинаковым селектором

Page 106: Жизнь в изоляции

100

.foo { color: red; width: 100px;}.bar { color: green;}

Но в таком случае бессилен

селекторы разные

Page 107: Жизнь в изоляции

Понимание границ верстки дает возможность для больших

оптимизаций

101

Границы обеспечивает изоляция стилей

Page 108: Жизнь в изоляции

102

<b:style src="style.css"/><b:isolate/>!

<div class="foo bar"> ...</div>

.foo { color: red; width: 100px;}.bar { color: green;}

example.tmpl style.css

У нас есть все информация об использовании

foo и bar встречаются только на одном элементе

Page 109: Жизнь в изоляции

103

<b:style src="style.css"/><b:isolate/>!

<div class="s82jhs"> ...</div>

.s82jhs { color: red; width: 100px;}.s82jhs { color: green;}

example.tmpl style.css

Можно склеить

.foo + .bar

Page 110: Жизнь в изоляции

104

.s82jhs { width: 100px; color: green;}

example.tmpl style.css

<b:style src="style.css"/><b:isolate/>!

<div class="s82jhs"> ...</div>

Дальше за дело снова берется csso

Page 111: Жизнь в изоляции

Поиск ошибок и ликвидация мертвого кода

105

Page 112: Жизнь в изоляции

106

<b:style src="example.css"/>!

<span class="foo never-used"> ...</span>

.foo { /* ... */}.dead-style { /* ... */}

example.tmpl example.css

Если класс используется в разметке, но не используется в стилях или наоборот…

Не используемые имена классов

Page 113: Жизнь в изоляции

107

Инструменты нам скажут об этом

Page 114: Жизнь в изоляции

Проблемы отладки

108

Page 115: Жизнь в изоляции

109

Длинные префиксы, трудно искать исходник

Нет ссылки на оригинальный файл стилей

Page 116: Жизнь в изоляции

Префиксы

110

Page 117: Жизнь в изоляции

Мы определяем вид префикса, в зависимости от окружения

111

Page 118: Жизнь в изоляции

В режиме разработки используются префиксы вида

iNNN__

112

Где NNN – номер шаблона, часто совпадает между перезагрузками страницы

Page 119: Жизнь в изоляции

113

Короткие префиксы, легко отличать друг от друга

Page 120: Жизнь в изоляции

В боевой средеиспользуются base36 хеши h5fjy1bkfb4zcskh__

114

Page 121: Жизнь в изоляции

115

function generatePrefix(){ function base36(num){ return Math.round(num).toString(36); }!

// префикс должен начинаться с буквы var result = base36(10 + 25 * Math.random());!

while (result.length < 16) result += base36(new Date * Math.random());!

return result.substr(0, 16); }

Вероятность пересечения 1 / 5 747 921 912 739 067 000 000 000

Функция генерации префикса

Page 122: Жизнь в изоляции

Трансформация имен классов

116

Page 123: Жизнь в изоляции

Трансформация имен классов• В шаблоне:

.example

116

Page 124: Жизнь в изоляции

Трансформация имен классов• В шаблоне:

.example

• В документе – режим разработки:.i123__example

116

Page 125: Жизнь в изоляции

Трансформация имен классов• В шаблоне:

.example

• В документе – режим разработки:.i123__example

• В документе – боевая среда:.h5fjy1bkfb4zcskh__example

116

Page 126: Жизнь в изоляции

Трансформация имен классов• В шаблоне:

.example

• В документе – режим разработки:.i123__example

• В документе – боевая среда:.h5fjy1bkfb4zcskh__example

• В документе – боевая среда + сжатие имен:.Gh

116

Page 127: Жизнь в изоляции

117

Наша верстка в боевой среде

Page 128: Жизнь в изоляции

Поиск и ссылка на источник

118

Page 129: Жизнь в изоляции

Видео

119

Инструменты могут решить проблему поиска

Подробнее в докладе «SPA инструменты»

Page 130: Жизнь в изоляции

Видео

119

Инструменты могут решить проблему поиска

Подробнее в докладе «SPA инструменты»

Page 131: Жизнь в изоляции

120

Но как быть с информацией в Developer Tools?

Page 132: Жизнь в изоляции

121

.example { /* … */}!

style.css

Исходный файл стилей

Page 133: Жизнь в изоляции

122

.jdf9gd__example { /* … */}!

!

style.css?prefix=jdf9gd__

Подставляем префикс – получаем новый файл

Page 134: Жизнь в изоляции

123

.jdf9gd__example { /* … */}!

/*# sourceURL=style.css?prefix=jdf9gd__ */!

style.css?prefix=jdf9gd__

Добавляем sourceURL

Имя сгенерированного файла

Page 135: Жизнь в изоляции

124

.jdf9gd__example { /* … */}!

/*# sourceURL=style.css?prefix=jdf9gd__ *//*# sourceMappingURL=data:application/json;base64,... */

style.css?prefix=jdf9gd__

Добавляем карту кода

Содержимое карты кода в base64

Page 136: Жизнь в изоляции

125

btoa( JSON.stringify({ "version": 3, "sources": ["style.css"], "mappings": "AAAA" + ";AACA".repeat(css.split('\n').length) }))

Генерация карты с построчным соответствием

Оригинальное имя файла без префикса

Повторяем ";AACA" столько раз, сколько строк

Page 137: Жизнь в изоляции

126

Не забудьте включить карты кода для CSS

Page 138: Жизнь в изоляции

127

Ссылка на оригинальный файл стилей с правильным номером строкиPROFIT!

Page 139: Жизнь в изоляции

Не так важна реализация, главное – идея

128

Можете повторить у себя дома

Page 140: Жизнь в изоляции

EmberПодход №4.2

Page 141: Жизнь в изоляции

130

Более простая реализация

github.com/ebryn/ember-component-css

Осторожно – эксперимент!Ember 2.0

Page 142: Жизнь в изоляции

131

Изоляция достигается путем уникального класса

на корневом элементе компонента

Page 143: Жизнь в изоляции

132

& { padding: 2px;}.foo { color: red;}

example.hbs example.css

<div class="example-a34fba"> <span class="foo"> hello world </div></div>

Page 144: Жизнь в изоляции

133

.example-a34fba { padding: 2px;}.example-a34fba .foo { color: red;}

<div class="example-a34fba"> <span class="foo"> hello world </div></div>

example.hbs example.css

Page 145: Жизнь в изоляции

Проблемы• Пока на уровне прототипа

• Конфликты при вложении компонент

• Нет изоляции включений или стилей

• Под вопросом возможности отладки

134

Page 146: Жизнь в изоляции

В самом начале пути, но в правильном направлении

135

Page 147: Жизнь в изоляции

ReactПодход №4.3

Page 148: Жизнь в изоляции

137

+ +React Webpack PostCSS

(local-scope plugin)

tinyurl.com/m9xoefq

Page 149: Жизнь в изоляции

138

Изоляция достигается путем замены имен классов и id

и предоставления карты замен

Page 150: Жизнь в изоляции

139

!

Webpack

local-scope

.foo { background: red; }#bar { background: green; }

Оригинальный файл стилей

Page 151: Жизнь в изоляции

139

!

Webpack

local-scope

.foo { background: red; }#bar { background: green; }

Оригинальный файл стилей

Page 152: Жизнь в изоляции

139

!

Webpack

local-scope

.foo { background: red; }#bar { background: green; }

.ze2420…e8b7 { background: red; }#zdf120…a66d { background: green; }

Оригинальный файл стилей

Преобразованный файл стилей

Page 153: Жизнь в изоляции

139

exports.locals = { foo: "ze2420…e8b7", bar: "zdf120…a66d"}

!

Webpack

local-scope

.foo { background: red; }#bar { background: green; }

.ze2420…e8b7 { background: red; }#zdf120…a66d { background: green; }

Оригинальный файл стилей

Преобразованный файл стилей

Карта замен

Page 154: Жизнь в изоляции

140

loader: 'css?localIdentName=' + ( process.env.NODE_ENV === 'development' ? '[name]__[local]___[hash:base64:5]' : '[hash:base64:20]')

Можно управлять видом замены

В режиме разработки: MyComponent__foo___1rJwx

В боевом окружении: rJwx92gmbvaLiDdzgXiJ

Page 155: Жизнь в изоляции

141

import React from 'react';import styles from './MyComponent.css';!

class MyComponent extends React.Component { render() { return ( <div className={styles.foo}> <div className={styles.bar}> Local scope! </div> </div> ); }};

Используем оригинальные имена, не зная их текущего вида

Page 156: Жизнь в изоляции

В самом начале пути, но в правильном направлении

142

Hot! Появилось всего два месяца назад

Page 157: Жизнь в изоляции

Все идет к тому, что это будет стандартной функцией

загрузчика CSS в Webpack

143

Page 158: Жизнь в изоляции

Эпилог

Page 159: Жизнь в изоляции

Пока нет идеального способа изоляции стилей

145

Page 160: Жизнь в изоляции

Разработчики браузеров думают над проблемой

146

Page 161: Жизнь в изоляции

Возможно решением будет Shadow DOM

147

Page 162: Жизнь в изоляции

Пока же лучшая альтернатива пре- и пост-процессинг

148

Page 163: Жизнь в изоляции

Надежнее и больше возможностей

149

Page 164: Жизнь в изоляции

Вопросы?

150

Роман Дворнов @rdvornov [email protected]

basis.js basisjs.com

github.com/basisjs