CSSO — сжимаем CSS (часть 2)

116
CSSO — сжимаем CSS Роман Дворнов Avito Минск 2016

Transcript of CSSO — сжимаем CSS (часть 2)

Page 1: CSSO — сжимаем CSS (часть 2)

CSSO — сжимаем CSS

Роман Дворнов Avito

Минск 2016

Page 2: CSSO — сжимаем CSS (часть 2)

Работаю в Avito

Делаю SPA

Автор basis.js

Мейтенер CSSO

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

Page 3: CSSO — сжимаем CSS (часть 2)

3

Page 4: CSSO — сжимаем CSS (часть 2)

3

Page 5: CSSO — сжимаем CSS (часть 2)

4

«Хэппи-энда» не будет

Page 6: CSSO — сжимаем CSS (часть 2)

5

CSS-минификаторы не нужны!

Page 7: CSSO — сжимаем CSS (часть 2)

5Шутка… почтиCSS-минификаторы не нужны!

Page 8: CSSO — сжимаем CSS (часть 2)

6

Быстрые браузеры

«Тяжелые» сайты

Page 9: CSSO — сжимаем CSS (часть 2)

6

Быстрые браузеры

«Тяжелые» сайты

много CSS – нужно сжимать

Page 10: CSSO — сжимаем CSS (часть 2)

Чем сжимать?

Page 11: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 12: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 13: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 14: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 15: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 16: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 17: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 18: CSSO — сжимаем CSS (часть 2)

8

cssnanocsso clean-cssYUI Compressor fork

ycssmin

Герои сегодняшнего дня

Page 19: CSSO — сжимаем CSS (часть 2)

9

Минификаторов гораздо больше, но либо не популярны

либо слабо развиваются

Page 20: CSSO — сжимаем CSS (часть 2)

Сравниваем

Page 21: CSSO — сжимаем CSS (часть 2)

11

clean-css 3.4.9 cssnano 3.5.2 csso 2.0.0

bootstrap.css147 427 байт

118 186273 ms

117 4401 813 ms

117 756169 ms

foundation.css200 341 байт

142 667389 ms

145 0301 983 ms

144 262222 ms

normalize.css7 707 байт

17925 ms

182417 ms

1 8314 ms

reset.css1 092 байт

758 3 ms

77313 ms

7473 ms

goalsmashers.github.io/css-minification-benchmark/

Page 22: CSSO — сжимаем CSS (часть 2)

Выглядит как-то так…

Page 23: CSSO — сжимаем CSS (часть 2)

Библиотеки пишутся оптимально,

реальный CSS – нет

13

Page 24: CSSO — сжимаем CSS (часть 2)

14

clean-css 3.4.9 cssnano 3.5.2 csso 2.0.0

ActiAgent.ru602 233 байт (5 мес назад)

430 2401 077 ms

439 02423 270 ms

435 588531 ms

ActiAgent.ru822 021 байт (сейчас)

587 9061 705 ms

604 50348 550 ms

595 834616 ms

В gzip фактор сжатия 8 (~72Kb) Результат можно улучшить!

Наши цифры

Page 25: CSSO — сжимаем CSS (часть 2)

Минификация

Page 26: CSSO — сжимаем CSS (часть 2)

Все минификаторы работают похоже

Page 27: CSSO — сжимаем CSS (часть 2)

Базовая минификация

• Удаление

• Замена значений

• Структурная оптимизация

17

Page 28: CSSO — сжимаем CSS (часть 2)

Кажется, минификация CSS – это про знание спецификаций

18

Page 29: CSSO — сжимаем CSS (часть 2)

На деле – постоянно что-то вылазит

Page 30: CSSO — сжимаем CSS (часть 2)

Потому что

• Спецификации меняются

• Разная поддержка браузерами

• Баги браузеров

• Хаки

20

Page 31: CSSO — сжимаем CSS (часть 2)

Самое главное минификатор не должен ломать или чинить CSS

21

Page 32: CSSO — сжимаем CSS (часть 2)

Удаление

Page 33: CSSO — сжимаем CSS (часть 2)

Удаляем• Пробелы и комментарии (основной выигрыш)

• Правила с неверными селекторами

• Пустые правила

• Неверные декларации

• Неверно расположенные @import, @charset

• …

23

Page 34: CSSO — сжимаем CSS (часть 2)

Но нужно учитывать особенности спецификаций

24

Page 35: CSSO — сжимаем CSS (часть 2)

25

calc(4 * 2em - 10% / 3)Оригинальный CSS

Не правильно

calc(4*2em-10%/3)

Правильно

calc(4*2em - 10%/3)

Удаление пробелов

Page 36: CSSO — сжимаем CSS (часть 2)

Еще примеры• Единицы измерения у нулей0px ! 0

• Кавычки[attr="name"] ! [attr=name] url('image.png') ! url(image.png)

• …

26

Page 37: CSSO — сжимаем CSS (часть 2)

Но всегда есть нюансы…• 0px ! 0 можно

27

Page 38: CSSO — сжимаем CSS (часть 2)

Но всегда есть нюансы…• 0px ! 0 можно

• 0deg ! 0 нельзя, так как не длина

27

Page 39: CSSO — сжимаем CSS (часть 2)

Но всегда есть нюансы…• 0px ! 0 можно

• 0deg ! 0 нельзя, так как не длина

• flex: 1 0 0px ! flex: 1 0 0 нельзя, сломается в IE

27

Page 40: CSSO — сжимаем CSS (часть 2)

Замена

Page 41: CSSO — сжимаем CSS (часть 2)

Замена значений на более короткие эквиваленты

29

Page 42: CSSO — сжимаем CSS (часть 2)

Наиболее интересное: цвет• hsl ! rgb, hsla ! rgba

• rgb(100%, 0, 0) ! rgb(255, 0, 0)

• rgba(a, b, c, 1) ! rgb(a, b, c)

• нормализация: rgb(500, -100, 0) ! rgb(255, 0, 0)

• rgb(255, 0, 0) ! #ff0000

• #aabbcc ! #abc

• #ff0000 ! red, darkslateblue ! #483d8b30

Page 43: CSSO — сжимаем CSS (часть 2)

Что еще• Нормализация чисел: 0.00 ! 0 или 0.123 ! .123

• Специфика для свойств

• font-weight:bold ! font-weight:700

• background:none ! background:0 0

• from ! 0%, 100% ! to в @keyframes

• …

31

Page 44: CSSO — сжимаем CSS (часть 2)

Не сильно эффективно

Page 45: CSSO — сжимаем CSS (часть 2)

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

Page 46: CSSO — сжимаем CSS (часть 2)

Слияние и перемещение деклараций и правил

34

Page 47: CSSO — сжимаем CSS (часть 2)

Самая сложная и ресурсоемкая оптимизация

Page 48: CSSO — сжимаем CSS (часть 2)

36

.foo { color: red; color: green;}

.foo { color: green;}

Удаление ненужных деклараций

color: red никогда не будет использовано браузером – можно удалить

Page 49: CSSO — сжимаем CSS (часть 2)

Внимание! Викторина Насколько вы хороший минификатор ;)

37

Page 50: CSSO — сжимаем CSS (часть 2)

38

.foo { color: red; color: rgba(…);}

.foo { color: rgba(…);}

Удаление ненужных деклараций

Правильно?

Page 51: CSSO — сжимаем CSS (часть 2)

38

.foo { color: red; color: rgba(…);}

.foo { color: rgba(…);} НЕВ

ЕРНО

В старых браузерахне поддерживается rgba()

Удаление ненужных деклараций

Правильно?

Page 52: CSSO — сжимаем CSS (часть 2)

39

.foo { color: red;}.bar { color: green;}.qux { color: red;}

.foo, .qux { color: red;}.bar { color: green;}

ПерегруппировкаПравильно?

Page 53: CSSO — сжимаем CSS (часть 2)

39

.foo { color: red;}.bar { color: green;}.qux { color: red;}

.foo, .qux { color: red;}.bar { color: green;}

НЕВЕРН

О

Разный эффект, например:<div class="bar qux">

ПерегруппировкаПравильно?

Page 54: CSSO — сжимаем CSS (часть 2)

40

span { color: red;}div { color: green;}ul { color: red;}

span, ul { color: red;}div { color: green;}

ПерегруппировкаПравильно?

Page 55: CSSO — сжимаем CSS (часть 2)

40

span { color: red;}div { color: green;}ul { color: red;}

span, ul { color: red;}div { color: green;}

Правильно, у элементов одно имя

ПерегруппировкаПравильно?

Page 56: CSSO — сжимаем CSS (часть 2)

41

.foo { color: red;}span { color: green;}.bar { color: red;}

.foo, .bar { color: red;}span { color: green;}

ПерегруппировкаПравильно?

Page 57: CSSO — сжимаем CSS (часть 2)

41

.foo { color: red;}span { color: green;}.bar { color: red;}

.foo, .bar { color: red;}span { color: green;}

Правильно,разная специфичность –порядок не важен

ПерегруппировкаПравильно?

Page 58: CSSO — сжимаем CSS (часть 2)

42

.foo { color: red;}.bar:not(.baz) { color: red;}

.foo,

.bar:not(.baz) { color: red;}

ПерегруппировкаПравильно?

Page 59: CSSO — сжимаем CSS (часть 2)

42

.foo { color: red;}.bar:not(.baz) { color: red;}

.foo,

.bar:not(.baz) { color: red;}

ПерегруппировкаПравильно?

Старые браузеры не поддерживают :not()

НЕВЕРН

О

Page 60: CSSO — сжимаем CSS (часть 2)

43

И т.д. и т.п.

Page 61: CSSO — сжимаем CSS (часть 2)

44

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

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

Вынос общих частей

Page 62: CSSO — сжимаем CSS (часть 2)

Выносить можно в каждом случае по-разному

45

Page 63: CSSO — сжимаем CSS (часть 2)

46

.foo { color: red;}.bar { color: red; color: rgba(..);}

.foo, .bar { color: red;}.bar { color: rgba(..);}

Вынос общих частей

В данном примере можно только в начало

Page 64: CSSO — сжимаем CSS (часть 2)

47

.foo { color: rgba(..);}.bar { color: red; color: rgba(..);}

.bar { color: red;}.foo, .bar { color: rgba(..);}

Вынос общих частей

В данном примере можно только в конец

Page 65: CSSO — сжимаем CSS (часть 2)

Очень много нюансов, нужно знать специфику свойств и селекторов

48

Page 66: CSSO — сжимаем CSS (часть 2)

Базовая оптимизация• Похожие методы

• Основной выигрыш дает удаление пробелов

• Много хаков

• У всех есть ошибки

49

Page 67: CSSO — сжимаем CSS (часть 2)

Продвинутые оптимизации

Page 68: CSSO — сжимаем CSS (часть 2)

Usage data

Usage data

Page 69: CSSO — сжимаем CSS (часть 2)

52

.foo { color: red;}.bar { color: green;}.qux { color: red;}

.foo, .qux { color: red;}.bar { color: green;}

Трансформация не безопасна, так как мы не знаем как используется CSS в разметке

Вспомним пример

Page 70: CSSO — сжимаем CSS (часть 2)

Но что, если мы знаем как используется?

53

Page 71: CSSO — сжимаем CSS (часть 2)

Фильтрация

Page 72: CSSO — сжимаем CSS (часть 2)

55

{ "classes": ["foo", "bar"], "tags": ["ul", "li"]}

.foo { color: red }div.bar { color: green }ul li, ol li { color: blue }

usage.json

CSS

+ .foo { color: red }ul li { color: blue }

Результат

Page 73: CSSO — сжимаем CSS (часть 2)

Scopes

Page 74: CSSO — сжимаем CSS (часть 2)

Пример

57

.module1-foo { background: red; }

.module1-bar { font-size: 1.5em; background: yellow; }

.module2-baz { background: red; }

.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }

Нельзя объединить .module1-foo и .module2-baz,

так как между ними .module1-bar

Page 75: CSSO — сжимаем CSS (часть 2)

Пример

58

.module1-foo { background: red; }

.module1-bar { font-size: 1.5em; background: yellow; }

.module2-baz { background: red; }

.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }

Минификатор не знает, что имена не смешиваются

и можно безопасно перемещать

Page 76: CSSO — сжимаем CSS (часть 2)

Usage data

59

{ "scopes": [ ["module1-foo", "module1-bar"], ["module2-baz", "module2-qux"] ]}

Так мы гарантируем, что классы module1-* и module2-*

не встречаются на одном элементе

Page 77: CSSO — сжимаем CSS (часть 2)

Результат с usage data

60

.module1-foo,.module2-baz{background:red}

.module1-bar,.module2-qux{font-size:1.5em;background:#ff0}

.module2-qux{width:50px}

На 29 байт меньше, чем без usage data

Page 78: CSSO — сжимаем CSS (часть 2)

61

Уже поддерживается в CSSO!

Page 79: CSSO — сжимаем CSS (часть 2)

Что это дало нашему проекту

• 823 Kb Оригинальный CSS

• 596 Kb Базовая минификация

• 437 Kb Минификация с usage data

62

Улучшение результата на 159Kb (26%)

Page 80: CSSO — сжимаем CSS (часть 2)

Как генерировать usage data?

63

Универсального решения нет – все зависит от используемого стека

Page 81: CSSO — сжимаем CSS (часть 2)

Rename

Rename

Page 82: CSSO — сжимаем CSS (часть 2)

65

.foo { color: red }

.foo.bar { color: green }

.a { color: red }

.a.b { color: green }

{ "foo": "a", "bar": "b"}

rename map

Результат

CSS+

Page 83: CSSO — сжимаем CSS (часть 2)

66

• 823 Kb Оригинальный CSS

• 596 Kb Базовая минификация

• 385 Kb Rename (пока вне CSSO)

Улучшение результата на 211Kb (35%)

Что это дало нашему проекту

Page 84: CSSO — сжимаем CSS (часть 2)

67

Улучшение результата на 364Kb (61%)

Все вместе

• 823 Kb Оригинальный CSS

• 596 Kb Базовая минификация

• 232 Kb Rename + Usage data

Page 85: CSSO — сжимаем CSS (часть 2)

Должно ли это быть в минификаторе?

68

Page 86: CSSO — сжимаем CSS (часть 2)

69

.foo,

.bar { color: red;}.foo:hover,.bar:hover { color: green}

.a { color: red }

.a:hover { color: green }

{ "foo": "a", "bar": "a"}

rename map

РезультатCSS

+

Page 87: CSSO — сжимаем CSS (часть 2)

Кто будет писать такой CSS?

70

Usage data!

Page 88: CSSO — сжимаем CSS (часть 2)

71

.foo { color: red;}.foo:hover { color: green}

.bar { color: red;}.bar:hover { color: green}

РезультатCSS + usage data.foo,.bar { color: red;}.foo:hover,.bar:hover { color: green}

Page 89: CSSO — сжимаем CSS (часть 2)

В разработке – скоро в CSSO

Page 90: CSSO — сжимаем CSS (часть 2)

73

• ~10 Kb дополнительного выигрыша (~3-4%)

• 1431 удаленный селектор из 6904

Селекторов стало на ~20% меньше

Что это дало нашему проектупредварительные оценки

Page 91: CSSO — сжимаем CSS (часть 2)

74

Сжимать или не сжимать?

Page 92: CSSO — сжимаем CSS (часть 2)

На что влияет минификация?

75

Page 93: CSSO — сжимаем CSS (часть 2)

76

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Как CSS превращается в картинку

Page 94: CSSO — сжимаем CSS (часть 2)

77

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Влияние характеристик CSS на скорость

Влияют количественные характеристики CSS (размер, кол-во селекторов и т.д.)

Влияют качественные характеристики CSS (сложность расчетов и отрисовки)

Page 95: CSSO — сжимаем CSS (часть 2)

78

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Автоматизация улучшений

Компрессия может оказать положительный эффект

Пока нет предпосылок, что задача решается

Page 96: CSSO — сжимаем CSS (часть 2)

79

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Network

Решение: gzip, SDCH …

Имеет эффект только для холодной загрузки

Неоптимизированный CSS сжимается лучше

Page 97: CSSO — сжимаем CSS (часть 2)

80

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Parse Stylesheet

Решение: сжатие CSS

Тут gzip уже не играет роли, выполняется всегда на старте + мутация DOM

Меньше текста – меньше парсить

Page 98: CSSO — сжимаем CSS (часть 2)

Без сжатия 823 Kb – 35ms Базовое сжатие 596 Kb – 29ms

Rename 385 Kb – 24ms Rename + usage data 232 Kb – 22ms

81

Наколеночные тестВлияние разного уровня сжатия на время парсинга

Размер уменьшился в ~4 раза, но время лишь на ~50%

(Chrome на MacBook Air)

Page 99: CSSO — сжимаем CSS (часть 2)

Win10 Desktop 19ms → 11ms Nexus 5X 68ms → 44ms

Samsung Galaxy Note 2 158ms → 108ms 82

Наколеночные тесты

Ранее, на других устройствах, были получены более обнадеживающие цифры при улучшении сжатия

CSS 316Kb 215Kb (-39.5%)+ usage data

Page 100: CSSO — сжимаем CSS (часть 2)

83

Network

Paint

Parse Stylesheet

Recalculate Style

Layout

Parse Stylesheet

Решение: rename и др.

Уменьшение кол-ва селекторов, их сложности

Пока гипотезы, цифр нет, но будут как только фича появится в CSSO ;)

Page 101: CSSO — сжимаем CSS (часть 2)

Сжимать или не сжимать?

84

Page 102: CSSO — сжимаем CSS (часть 2)

Сжимать или не сжимать?

84

Да! Хуже не будетХотя эффект – предмет для исследований

Page 103: CSSO — сжимаем CSS (часть 2)

CSSO – новая жизнь

Page 104: CSSO — сжимаем CSS (часть 2)

Что изменилось• В 10+ раз быстрее

• В 8+ раз меньше потребление памяти

• Исправлена большая часть проблем и багов

• Улучшена кодовая база и API

• Больше скачиваний и звезд на GitHub ;)86

Page 105: CSSO — сжимаем CSS (часть 2)

87

Врем

я сж

атия

CSS

(600

Kb)

500 ms

1 000 ms

1 500 ms

2 000 ms

2 500 ms

3 000 ms

3 500 ms

4 000 ms

4 500 ms

5 000 ms

5 500 ms

6 000 ms

Версия CSSO

1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 2.0

1 050 msclean-css

Изменение по скорости

csso500 ms

cssnano23 250 ms

Page 106: CSSO — сжимаем CSS (часть 2)

postcss-csso

88

Плагин для PostCSS, aльтернатива cssnano

Работает почти также быстро как CSSO отдельно

Под капотом конвертация AST

github.com/lahmatiy/postcss-csso

Page 107: CSSO — сжимаем CSS (часть 2)

89

1 300 000+ скачиваний в месяцx9 с октября 2015

Page 108: CSSO — сжимаем CSS (часть 2)

Новое• Source Maps

• Usage data

• Лучше поддержка "новых" частей в CSS

• Лучше сообщения об ошибках

• Поддержка stdin

• Новый формат AST

90

Page 109: CSSO — сжимаем CSS (часть 2)

Планы

Page 110: CSSO — сжимаем CSS (часть 2)

Главная цель – лучший минификатор

Page 111: CSSO — сжимаем CSS (часть 2)

Coming soon• Новые оптимизации и алгоритмы: быстрее и правильно

• Учет поддерживаемых браузеров

• Семейства свойств и сортировка деклараций

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

• Понимание структуры shorthand-значений

• Применение статистики

93

Page 112: CSSO — сжимаем CSS (часть 2)

В заключении

Page 113: CSSO — сжимаем CSS (часть 2)

Любите CSS, читайте спеки

Page 114: CSSO — сжимаем CSS (часть 2)

96Используйте CSSO :)

Page 115: CSSO — сжимаем CSS (часть 2)

97

Все новое в твитере @cssoptimizer

Page 116: CSSO — сжимаем CSS (часть 2)

Роман Дворнов @rdvornov

[email protected]

Вопросы?

github.com/css/csso