Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

CSSO

Ребята из симферопольского «Яндекса» сказали новое слово в оптимизации CSS — CSSO. Оптимизатор интересен тем, что умеет минимизировать с изменением структуры — то есть удалять перекрываемые свойства, производить слияние блоков с одинаковыми селекторами и тому подобное.

Сергей Крыжановский, который занимается программированием CSSO, в своём блоге хорошо описал отличия CSSO от YUI Compressor, CSSTidy и им подобных.

Например, CSSO умеет вот такое:

/* до CSSO */
.a {
    color: red;
    border: 0;
}

.b {
    color: red;
}

/* после CSSO */
.a{border:0}.a,.b{color:red}

Меня несказанно печалит, что оптимизатор написан на JavaScript, потому что хостинг с серверным JS найти крайне проблематично, но зато оптимизацию в действии можно попробовать прямо в браузере.

42 комментария
parpalak (written.ru) 2011

А я правильно понимаю, что такая оптимизация CSS, как в примере выше, несколько противоречит рекомендациям по повышению скорости рендеринга в браузерах (из-за того, что .a встречается два раза):
http://code.google.com/speed/page-speed/docs/rendering.html#UseEfficientCSSSelectors

Или браузеры при парсинге CSS догадываются объединять эти две группы правил для .a в одну?

Евгений Степанищев (bolknote.ru) 2011

Комментарий для written.ru:

Или браузеры при парсинге CSS догадываются объединять эти две группы правил для .a в одну?

Честно сказать, не представляю как может быть иначе.

greli (greli.livejournal.com) 2011

Комментарий для written.ru:

Проигрышь в скорости рендеринга, если и будут, то доли микросекунды, а выигрыш благодаря уменьшению размера куда более заметен. Сетевые задержки могут составлять секунды, а процессор обработает этот случай куда быстрее, чем будет передаваться лишние байты.

skryzhanovsky 2011

Комментарий для Евгения Степанищева:

При написании CSSO изначально закладывался потенциал портирования на другие языки. JS там очень простой, магия [почти] не применяется. Фактически, для каждой функции примерял то, как она будет выглядеть на Java, C++, Python и т. д. Вроде проблем не будет. Когда релиз выйдет на 2.0.0 (сейчас всё-таки слишком много TODO), можно будет плавно портировать.

skryzhanovsky 2011

Комментарий для written.ru:

Такие потери — больше теория, чем практика.

  1. Парсеры браузеров тратят на разбор CSS миллисекунды, это копейки в сравнении со всем остальным. Плюсминус копейка — даже толком не измерить, т. к. войдёт в погрешность.
  2. Результат разбора уходит во внутренние структуры, которые гораздо, гораздо сложнее того, как выглядит текст CSS. В одном браузере группы объединятся, в другом размножатся (утрирую, но). Внутри свои алгоритмы и свои правила, пытаться учитывать их смысла нет.
Orcinus Orca (orcinus.ru) 2011

А я всегда использовал перечисление, как здесь используется. Никаких тормозов не замечал. И вроде все браузеры на это адекватно смотрят.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky:

При написании CSSO изначально закладывался потенциал портирования на другие языки. JS там очень простой, магия [почти] не применяется.

Да, я смотрел, код правда простой.

Кстати, если ты сразу смотрел на другие языки, тогда можно было написать какой-нибудь простой интерпретатор инструкций (DSL), тогда инструкции можно было бы обновлять сразу на всех языках.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky:

skryzhanovsky

Можно использовать «skryzhanovsky.ya.ru» вместо имени, тогда сразу по OpenID будет.

Orcinus Orca (orcinus.ru) 2011

Комментарий для Евгения Степанищева:

А у меня заработал OpenID на твоем блоге.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для orcinus.ru:

Не работал раньше?

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

А разверни мысль про DSL, а то я сейчас нафантазировал вплоть до первичной компиляции CSS в CSS-байткод. :)

Orcinus Orca (orcinus.ru) 2011

Комментарий для Евгения Степанищева:

Да, я тебе по этому поводу писал. А тут, смотрю сегодня — заработал.

boltai-shaltai 2011

Мне сейчас кажется, что в режиме структурной оптимизации должны только выдаваться предупреждения, но код трогать не надо. Исходный код на основе выданных ворнингов должен реструктурировать сам верстальщик, если захочет. Иначе такой исходный CSS будет просто «плохим» кодом, не готовым для продакшена — непродуманным, избыточным, плохо струтурированным. Зачем интеллектуальную (не очень алгоритмизируемую) работу по структурированию отдавать оптимизатору?

А часто повторяемость намеренно добавляется для удобочитаемости. И я бы её просто оставлял в покое, не выкусывал — процент в хорошем коде совсем невелик и погоды не сделает. Но это умозрительное имхо, конечно. Надо просто попробовать на «хорошем» коде )) Может, кто-то пробовал уже?

Но однозначно тулза пригодится для «плохого»/чужого кода. Иногда с первого взгляда видно — каша! покоцать её не глядя.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

А разверни мысль про DSL, а то я сейчас нафантазировал вплоть до первичной компиляции CSS в CSS-байткод. :)

Не, я не про это. Придумать язык, на котором можно было бы выражать конструкции оптимизации. Что-то в сторону БНФ, плюс некий язык для правил изменения кода.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для boltai-shaltai:

Дело в том, что CSS’ы объёмом в 50..70Kb — уже не редкость. Там сотни селекторов и тысячи свойств. В итоге получим под сотню предупреждений и рекомендаций, а разработчик это будет руками разводить? Дык уже не разводят, потому с середины прошлого десятилетия минимизаторы и пошли толпой.
Удобочитаемость — результат минимизации не предназначен для чтения человеком. Это сродни компиляции.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

А, понятно. Я зачатки такого уже сделал, правда, пока лишь в запретительных целях («не удаляй свойство», «не меняй порядок»). Посмотрим, будет ли удобно и в каком виде такой почти-DSL в CSS внедрять.

boltai-shaltai 2011

Комментарий для skryzhanovsky.ya.ru:

Дык уже не разводят

Вы тоже? Не верю. Любой _нормальный_ кодер, которому к тому же не капают на мозги и не гонят на скорость, всё же стремится написать стройный код.

Это сродни компиляции.

Нну.. вот и плохо, что так пишут. Разгребать такой код весьма противно. Я не хотел бы оставлять за собой такую пакость.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

А, понятно. Я зачатки такого уже сделал, правда, пока лишь в запретительных целях («не удаляй свойство», «не меняй порядок»).

Не-не, ты другое говоришь. Ты сейчас про запретительные инструкции в CSS, а я про то, чтобы парсер и оптимизатор делать не на JS, а на DSL, а интерпретатор DSL уже делать на нужном языке.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для boltai-shaltai:

Вы тоже? Не верю. Любой _нормальный_ кодер, которому к тому же не капают на мозги и не гонят на скорость, всё же стремится написать стройный код.

Кажется, упускаете два распространённых случая:

  1. Генерация CSS. Каждый раз руками допиливать за каким-нибудь не очень чисто работающим роботом — то ещё удовольствие.
  2. Собираемый CSS. Как ни старайся, а при склейке сотни блоков окажется избыточность. Каждый раз после сборки её устранять — тоже серьёзная трата времени.

Нну.. вот и плохо, что так пишут. Разгребать такой код весьма противно. Я не хотел бы оставлять за собой такую пакость.

Повторю: CSS в 50..70Kb. :) Разработчик может быть сколь угодно гениальным, но удержать в голове контекст такого объёма и постоянно в голове же оптимизировать... Ну, возможно, да. На это будет уходить половина рабочего времени.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

Теперь понятнее. :) Такой вариант рассматривал, но отклонил. Я хочу позже написать немножко записей о минимизации, там же опишу причины, по которым CSSO на JS и сделан так, как сделан. Сейчас бегло получится, потому плохо. Но поверь, причины решений есть. :)

boltai-shaltai 2011

Комментарий для skryzhanovsky.ya.ru:

Про генерируемый код согласен.
Про собираемый — не совсем понятно. Собираются же фрагменты, описывающие независимые элементы? Откуда там повторы, если классы разные?

удержать в голове контекст такого объёма

Под «хорошим» кодом я имел в виду такой, который как раз не надо держать в голове целиком. Те же «независимые блоки» вполне снимают головную боль, ограничивая контекст.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для boltai-shaltai:

Классы разные, свойства и значения свойств одинаковые. Упростим до немного детского примера: .myclass0 { color: red } .myclass1 { color: red }.
В худшем случае после сборки итогового CSS из запчастей мы получим простыню из такого перечисления классов.
Думается, работу по превращению такой простыни в .myclass0,.myclass1 { color: red } лучше переложить на плечи роботов.

boltai-shaltai 2011

Комментарий для skryzhanovsky.ya.ru:

Нда, я тут проклинил и говорил больше о тупом копипастерстве, о явной избыточности. А такая группировка как самоцель как-то вылетела из головы.

А она что, реально экономит объём? Селекторы с именами классов и иерархией бывают довольно объёмные, и их «размножение» при группировке по свойствам может раздуть объём. Я понимаю, что вы там всё взвешиваете, на то и оптимизация. Но на реальном-то коде что происходит, есть у вас оценки?

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для boltai-shaltai:

Очень зависит от того, какой CSS подаётся на вход. Тут как с архивированием: сжимать сжатое уже никак.
На больших грязных CSS выигрываем от 2% до 5% без особой магии. На мелких обычно меньше. Правда, следует учитывать, что пока не все варианты группировок добавлены, а shorthand’ы покрыты только margin/padding, потому можно оптимистично добавить ещё 1%..2%.

Vladimir Moskva (fulc.ru) 2011

хостинг с серверным JS найти крайне проблематично

VPS легко найти, кроме того, сжимать можно и на локальной машине.

Orcinus Orca (orcinus.ru) 2011

Комментарий для boltai-shaltai:

Решил проверить на своем сайте.
До оптимизации: 1884 байта
После оптимизации: 1543 байта.
Получилась экономия в 341 байт.
Если бы там использовалась оптимизация по font-family, то код сократился бы очень сильно.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для fulc.ru:

VPS легко найти

Это другие деньги.

кроме того, сжимать можно и на локальной машине.

Очень неудобно. Я часто редактирую мелочи прямо на удалённой машине.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для orcinus.ru:

Если бы там использовалась оптимизация по font-family, то код сократился бы очень сильно.

А попробуйте прогнать через YUI Compressor, потом через CSSO.

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для orcinus.ru:

Добавил сегодня одну из схем группировок, теперь ваш CSS сжимается до 1308 байт. :)
На всякий случай отмечу: это не схема именно по font-family, просто в вашем случае именно повторы font-family удачно попали под новую группировку.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Смотри, я нашёл как улучшить алгоритм:

{ font-family: Tahoma; color: red }

{ color: red }

{ font-family: Tahoma; }

CSSO объединяет классы «.a» и «.b», что неправильно, там общее место — «color: red», оно короче, чем «font-family: Tahoma», объединять надо классы «.a» и «.c»!

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Более того, должно получиться вот так:
.a, .c { font-family: Tahoma }
.b, .a { color: red }

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

Такую минимизацию уже проходил в ветке 1.0.x, после чего срочно переделал на менее опасную. :) В общем случае (обрати внимание на «в общем случае») нельзя нарушать порядок следования селекторов, это может плохо закончиться при комбинации классов у элемента. В твоём примере из abc получился acba, что может сломать вёрстку.

PS. Добавил бы подчёркивание в разметку комментов. :)

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Такую минимизацию уже проходил в ветке 1.0.x, после чего срочно переделал на менее опасную. :) В общем случае (обрати внимание на «в общем случае») нельзя нарушать порядок следования селекторов, это может плохо закончиться при комбинации классов у элемента. В твоём примере из abc получился acba, что может сломать вёрстку

Видимо, на ночь глядя, я не очень понимаю в чём опасность. Поясни на примере, пожалуйста!

PS. Добавил бы подчёркивание в разметку комментов. :)

Ну уж нет. Подчёркивание должно быть только в ссылках. :)

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

Пожалуй, самый наглядный пример:

test0.css: .t0 { color: red } .t1 { color: green }
test1.css: .t1 { color: green } .t0 { color: red }

test.html: <div class=«t0 t1»>test</div>

В случае с test0.css получишь текст зелёного цвета, а test1.css даст красный цвет.

Пример кажется простым и очевидным. И кажется, что «ну хорошо, в таких случаях не менять порядок, конечно, но наверняка иногда можно», но кажется так ошибочно. Распространи проблему на большой CSS, на сотни селекторов и тысячи свойств, да ещё и на множественные комбинации классов у элемента. Попытка безопасно перетрясти такое выливается в адову лапшу «частных случаев» с постоянной опасностью упустить какой-нибудь сотый случай, когда нельзя было даже дышать на селектор.

Может быть, в будущем снова залезу и что-то получится, но пока целью является гарантированное сохранение результата рендеринга даже в ущерб потенциальному отгрызанию размера.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Не вижу как это пересекается с моим примером. Можешь показать как с моим примером может получиться что-то плохое?

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для Евгения Степанищева:

Жень, ведь специально выделил «в общем случае» и «может», а потом упомянул «частные случаи». В твоём примере ничего плохого. :)

На деле я просто не готов сейчас написать обстоятельно и убедительно на эту тему. Более того, вполне вероятно, что дую на воду после молока, и преувеличиваю опасности. Предлагаю вернуться к разговору после того, как CSSO исчерпает минимизации без смены селекторов, а я для этой области минимизаций составлю каталог.

Евгений Степанищев (bolknote.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Ok!

Orcinus Orca (orcinus.ru) 2011

Комментарий для skryzhanovsky.ya.ru:

Отлично смотрится. Удачных поисков в оптимизации.

C'est la vie (se-la-vy.blogspot.com) 2011

Всё бы замечательно, только ant`а таска для CSSO найти не удаётся...

Для YUI Compressor`а, например, есть (описан, например, на «Техногрете»: http://www.artlebedev.ru/tools/technogrette/soft/eclipse-ant/ ), и очень удобно настроив один раз проект, потом оптимизировать все файлы автоматом при внесении изменений.
А так — всё выглядит очень здорово! Спасибо Вашей конторе за такой замечательный проект!
Так что ждём, надеемся и верим! :)

Сергей Крыжановский (skryzhanovsky.ya.ru) 2011

Комментарий для se-la-vy.blogspot.com:

Таски (плагины) для Ant / Maven удобнее будет делать после того, как релиз CSSO портируется на Java. Потому не сейчас, но обязательно. :)
Спасибо.

usedspareparts.ru/ 2011

Комментарий для skryzhanovsky.ya.ru:

Сергей, еще момент.
Пробел перед !important.

se-la-vy.blogspot.com 2011

Комментарий для skryzhanovsky.ya.ru:

Ясно. А если через Rhino прогнать?