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)

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

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

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

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

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

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

greli (greli.livejournal.com)

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

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

skryzhanovsky

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

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

skryzhanovsky

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

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

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

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

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

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

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

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

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

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

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

skryzhanovsky

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

Orcinus Orca (orcinus.ru)

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

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

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

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

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

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

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

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

Orcinus Orca (orcinus.ru)

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

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

boltai-shaltai

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

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

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

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

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

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

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

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

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

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

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

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

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

boltai-shaltai

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

boltai-shaltai

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

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

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

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

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

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

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

boltai-shaltai

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

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

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

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

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

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

Vladimir Moskva (fulc.ru)

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

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

Orcinus Orca (orcinus.ru)

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

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

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

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

VPS легко найти

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

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

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

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

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

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

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

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

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

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

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

Комментарий для 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)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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)

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

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

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

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

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

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

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

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

Ok!

Orcinus Orca (orcinus.ru)

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

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

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

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

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

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

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

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

http://usedspareparts.ru/

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

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

se-la-vy.blogspot.com

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

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

Популярное