Андрей Ситник ( Iskin, Злые марсиане)
В 2013 году Holowaychuk анонсировал свой проект Rework в статье «Модульный CSS-препроцессинг с Реворком» (http://tjholowaychuk.tumblr.com/post/44267035203/modular-css-preprocessing-with-rework ).
Как раз тогда я искал какой-то инструмент для того, чтобы сделать автопрефиксер. Когда я прочитал эту статью, я был поражен, потому что это был действительно революционный подход, он менял все. И поэтому первые версии автопрефиксера базировались на Rework’е. Но, к сожалению, Rework – это был Proof Of Concept, это было первое поколение, чтобы доказать, что это вообще работает. Поэтому мы его жестко форкнули, переманили всех разработчиков, устроили маленькую революцию и сделали PostCSS.
PostCSS – это второе поколение модульного процессора.
Так что же такое PostCSS?
PostCSS – это модульный препроцессор, в ядре которого очень простое. Ядро состоит из двух вещей:
- Парсер, который на вход принимает CSS-строку и на выход выдает дерево объектов javascript’овских. AST (абстрактное синтаксическое дерево).
- Стригифайр, который он делает обратную вещь – он на вход получает то абстрактное дерево в виде объектов, и на выход выдает новый CSS. По умолчанию ядро PostCSS очень удобное, очень полезное, но оно не делает ничего. Оно парсит ваш CSS, а потом обратно превращает его в строку и превращает так, что сохраняется байт в байт, даже пробельные символы.
Вся магия находится в этих плагинах.
Что такое плагин? Плагин – это такая javascript функция, которая на вход принимает AST, проходится по каким-то его узлам, что-то ищет, что-то меняет, что-то добавляет и измененное дерево возвращает обратно. В измененное дерево идет следующий плагин… Получается цепочка. А в конце – магический стригифайр, который берет это измененное дерево, сохраняет его в новую строку, и генерирует карты кода, сорсмэпа. Генерирует новые, либо обновляет старые.
Как говорил Торвальдс, «покажите мне код», потому что мы все программисты, код – это важно.
Как это выглядит? PostCSS – это NP-библиотека, мы грузим ее из NP. Далее мы создаем инстанс, создаем объект процессора и передаем те плагины, которые были на прошлом шаге и все. Мы берем и через этот процессор прогоняем наш CSS. И получаем результат с помощью промиса.
Пример плагина:
В препроцессорах нельзя сделать полифил для единицы измерения. Давайте напишем его на PostCSS. Плагин – это функция, которая на вход принимает CSS, дерево объектов, которое будет в переменной CSS. Далее у этого дерева есть такие волшебные функции – чтоб вам было удобно программировать, есть итератор по всем свойствам, внутри, оно рекурсивно. И мы берем и проходимся по всем свойствам. Это, кстати, заметьте ES6. Мы итерируемся по всем свойствам, ищем в свойствах значение rem и заменяем его на пиксели. Закрываем скобочки, потому что у нас, к сожалению, не CoffeeScript. Это весь код, который вам нужно написать, чтобы сделать такой базовый полифил для rem’a.
В чем разница?
Всегда нужно знать, кого бить, а кого нет, т.е. у нас должны быть точные критерии, где препроцессор, где постпроцессор. Препроцессор – он монолитный, все функции встроены в ядро, все переменные, примеси – все это там внутри, весь синтаксис. А вторая вещь – у вас код прямо в шаблоне, у вас полноценный язык программирования.
В PostCSS все в виде плагинов, ядро не делает ничего. А второй момент – у вас код и стили отдельно, получается, что у вас код на нормальном языке программирования javascript, a CSS – отдельно в CSS.
Почему это так важно? Потому что эти плагины реализуют магическую вещь – эволюцию.
Вам приходит какая-то безумная идея, и ваши друзья над вами смеются. Вы берете и реализуете ее в виде плагина, например, какой-то новый метод оптимизации, и публикуете его. Над вами, к сожалению, продолжают смеяться, потому что haters gonna hate, но, как минимум, некоторые люди понимают это, начинают это использовать, проверять. У них получается, их больше берут на работу, а тех, кто над вами смеялся, увольняют. Через некоторое время получается, что большинство пользователей пользуются вашим плагином. Не потому что идея красивая, а потому что она реально работает на практике. И когда у нас есть популярность, мы можем прийти в W3C и либо написать им черновик, либо попросить кого-то другого сделать спецификацию. Потому что делать спецификацию, когда у нас нет какого-то реального практического применения, нет практики, никто не знает, работает это или нет, никто не будет. Но если у вас есть популярность, вы пишете спецификацию и идете на новый круг, новые унижения, новый плагин и т.п.
Это была теория. Современная наука говорит очень правильную вещь – теория не значит ничего без практики. Если идея действительно работает, у нас будет реальный практический результат, у нас будет что-то. Если PostCSS работает, значит он будет лучше препроцессора, значит у нас будет что-то живое, что-то, что можно потрогать. Давайте посмотрим, есть ли это.
Первое. Само собой, в PostCSS есть переменные, это не сложно, есть вложенность, тоже не сложно, с амперсандом, как все любят, потому что БЭМ, само собой есть примеси, синтаксис чуть-чуть другой, но такой же. Но в чем важный момент? Все это сделано в виде плагинов. И переменные, и вложенность, и примеси. Например, для переменных есть два плагина, один плагин реализует старый добрый Sass-стиль, а другой реализует синтаксис W3C, css custom properties.
Второй важный момент – это то, что он невероятно маленький. Например, вложенность – это 60 строк обычного javascript-кода. Вы можете взять и исправить это, а если я откажусь это принять, вы можете взять и форкнуть. Это совершенно не проблема, вы за день можете сделать другую вложенность.
PostCSS это не про то, чтобы делать работу Sass’а модульно, потому что это же не так круто. Модульность – не модульность, кого это волнует? Главный вопрос: а можно ли сделать больше, можно ли сделать какую-то совершенно новую магию? И вот автопрефиксер – главный пример, т.е. вы просто пишете обычный CSS, а автопрефиксер сам. У него есть база данных Can I Use, он сам находит те свойства, которым нужны именно сейчас префиксы, добавляет их, при этом делая всякую сложную магию.
Более интересный пример cssnext.
В Javascript сейчас можно использовать тот Javascript, который еще не в браузерах, будущий. И у вас есть компилятор, который компилирует его в текущий. Было бы круто делать это все в CSS. Например, у нас есть CSS 4, там куча новых вкусных вещей. Например, можно объявить свой дополнительный селектор, кастомный, ваш личный и использовать его. И для этого у нас есть cssnext.
Cssnext – это транспайлер. Вы пишете CSS 4 прямо сейчас, а оно компилируется в CSS 3. Это к вопросу о том, что невозможно сделать на Sass. Кроме кастомных селекторов у вас, например, есть стандартизированная функция работа с цветом и, в том числе, всякие удобные сокращения. Прямо сейчас, можете прийти и добавить.
Но сейчас будет страшная история.
Китай, огромный рынок, много денег, все дела, но там творится – ужас! Там до сих пор популярен Е7, 8-ой и даже 6-ой. Это ужасно, а денег хочется. Поэтому китайская компания Alibaba написала плагин cssgrace. Это как cssnext, только наоборот. Он не из хорошего делает средний, а он, наоборот, из среднего делает плохой код. Она проходится по вашему CSS и находит те свойства, которые не будут работать в вашем Е, и заменяет их на хаки. Это немного похоже на примеси, но почему это круто, и почему это важно, что это невозможно на Sass? Потому что с примесями вам нужно помнить, где вам нужно написать примеси, вы должны помнить, что opacity не поддерживается. А тут вы просто пишете и не думаете об этом, а за вас думают китайцы, миллиард китайцев.
Кроме того, всякая магия со свойствами, и можно делать магию с селекторами. Есть жуткий хак, было бы круто сказать, что если у нас четыре элемента в родителе, то давай мы сделаем ширину 25%, а если пять, то 20. И это можно сделать прямо сейчас. Хак жуткий, вы вручную писать не будете, но с помощью этого плагина или PostCSS, он добавляет вам дополнительный селектор.
Или другая вещь. Выше все было про то, как писать код, а это про то, как делать код, чтоб ваш сайт грузился быстрее.
Есть спрайты, а есть бесидж 3 кодирование инлайн картинок, и у них есть свои плюсы и минусы. Вот было бы круто объединить их. При инлайне у вас разрастается ваша CSS, и получается, что когда пользователь заходит на сайт, пока он картинки не загрузит заинлайненные в CSS, он вообще ничего не увидит – это плохо. Было бы круто, если бы вначале загрузился дизайн, а потом картинки. И для этого есть волшебный плагин data-packer. Он проходится по вашему CSS, находит все картинки заинлайненные и выносит их в отдельный файл. Поэтому он обнаруживает, что два селектора используют одну и ту же картинку, и объединяет эти селекторы.
В итоге, когда пользователь заходит на сайт, он быстренько грузит маленький CSS дизайна, а потом долго CSS с картинками – удобно. Т.е. добавляете один плагин, и прямо сейчас ваш сайт становится быстрее.
Интересный момент. Кто поддерживает IЕ9? А кто поддерживает людей, у кого есть цветовая слепота? Проблема в том, что людей, которые не видят цвета, 5%, а пользователей IE старых – меньше. И это очень важно поддерживать. И нужно понимать, что это не черно-белое зрение. Все эти шутки про светофор – это не про цветовую слепоту. Например, так (слева) видит здоровый человек, а так (справа) видит человек с цветовой слепотой. Видите, что кнопка хуже заметна.
Это нужно тестировать, и с помощью PostCSS тестировать легко. Есть плагин. Вы во время разработки, например, делаете обычный билд и еще в один билд добавляете плагин. Этот плагин проходится по всем цветам вашего CSS и заменяет их на цвета, который видит человек с различными типами цветовой слепоты. Конечно же, есть более удобные инструменты, но мы же понимаем, что если вы не используете более удобные инструменты, значит, они вам не подходят. Но с помощью этого можете проверять сайт для людей с цветовой слепотой, используя эти простые инструменты.
Вот еще один интересный момент – PostCSS можно использовать не только, чтобы изменять ваш CSS, но и для того, чтобы его проверять. Например, Твиттер используют PostCSS для своего линтера, своего БЭМ-а. Это не очень клевый линтер, потому что простой, как все линтеры, которые вы уже, может быть, используете. А вот есть крутой линтер – doiuse:
Он работает как два префиксера, только он вас «линейкой бьет по пальцам». Он хранит в себе базу данных Can I Use, пробегается по вашему CSS и находит, что например: «Чувак, ты мне сказал, что ты IЕ хочешь поддерживать, а user selected не поддерживается IE, ты точно уверен, что ты его должен был написать?». Это очень удобная вещь.
Это мой самый любимый плагин. Так выглядит Википедия на иврите. Почему? Потому что евреи и арабы пишут в другую сторону. Это очень старое письмо. А дело в том, что (вы никогда не задумывались, почему будущее вон там – справа?) Будущее справа, потому что мы пишем слева направо. А если мы пишем в другую сторону, то будущее в нашей голове будет слева. И поэтому прогресс бар для евреев и арабов должен идти в другую сторону. И это касается не только прогресс бара, а вообще письменность влияет на восприятие пространства.
И что будет, если ИГИЛ возьмет вас в рабство и заставит верстать им сайты? Вы же не будете поддерживать две версии стилей. Одну для западной аудитории, а другую – для арабской. И поэтому парень из Иордана (он, вроде бы, не в ИГИЛ-е, слава богу) написал плагин, через который вы прогоняете CSS, и он заменяет left на right, right на left… И такую штуку он генерирует сам. Т.е. на вход обычная Википедия, а на выходе Википедия отзеркаленная. Это мой самый любимый плагин, который показывает, что невозможно на Sass.
Сейчас я рассказал только про те плагины, которые сейчас совсем невозможны на Sass’e, чтобы вас шокировать. На самом деле, у нас очень много разных плагинов, которые иногда более полезны, просто они не настолько круто выглядят. Вы можете зайти на наш github и посмотреть все плагины, там много интересного, много всякого синтетического сахара, оптимизации, расширения языка, поддержки старых браузеров и поддержки будущих браузеров.
Есть очень сложный вопрос. Я показал вещи, которые может делать PostCSS, которые невозможны на Sass. PostCSS может делать гораздо больше. Это невероятный, более мощный инструмент, но возникает вопрос: а может ли более мощный инструмент быть быстрее? Потому что в libsass сделали невероятную вещь с помощью оптимизации на Си, они очень быстры. Можно ли переплюнуть результат libsass? И ответ – да.
Это главный пример, почему модульная архитектура – это так круто, так важно. Потому что модульную архитектуру очень легко оптимизировать. У нас куча маленьких модулей. Мы можем понять, что у нас тормозит этот модуль, взять и оптимизировать его. И поэтому PostCSS написан на Javascript – в 4 раза быстрее libsass, написанный на С++. Это к вопросу о том, когда бэкендер будет говорить вам о том, что «давайте теперь пишем все на Си, это быстрее», то нет, это не быстрее.
Еще раз: какие преимущества PostCSS, почему оно лучше, чем Sass?
- PostCSS гораздо быстрее. Т.е. даже если вы довольны скоростью libsass, используя PostCSS, вы можете сделать больше вещей, вы можете делать какую-то более сложную оптимизацию. Это огромное пространство.
- Вторая вещь – это модульность, вы можете взять и форкнуть проект, вы можете использовать разные идеи.
- А третья вещь – самая важная, что PostCSS больше чем Sass. Вы можете на PostCSS делать любую фичу, которая есть в Sass, но на Sass вы не можете сделать большинство фич, которые есть в PostCSS.
Но я обманул вас. В названии доклада говорилось, что PostCSS – это будущее после Sass. На самом деле, это настоящее. У нас уже прямо сейчас больше полумиллиона загрузок в месяц с Can I Use. Огромная аудитория. Поэтому, если вы боитесь по поводу продакшн-реди, не бойтесь, мы действительно проверяем PostCSS на огромной аудитории. PostCSS пользуются очень большие компании.
Paul Irish говорил, что автопрефиксер с PostCSS используется в Google. Taobao – это крупнейший Интернет-магазин Китая, он не просто использует PostCSS, разные плагины, он их и пишет. Wordpress использует два плагина. Автопрефиксер rtl css – для арабской версии. И Твиттер не просто использует PostCSS, они в какой-то момент взяли и выкинули Less. У них используют только постпроцессоры. Только этот способ подхода.
Кроме того, PostCSS становится трендом. Например, A List Apart написала интересную статью о постпроцессорах, о том, как постпроцессоры PostCSS спасет нас от темной стороны CSS-процессоров (http://alistapart.com/column/what-will-save-us-from-the-dark-side-of-pre-processors).
Или например, перебежчик в наш лагерь, Бен Фрейн автор книги «Sass и Compass для дизайнеров» написал статью о том, как он расставался с Sass и переходил на PostCSS (http://benfrain.com/breaking-up-with-sass-postcss).
Но самый клевый твит, это конечное же, Bootsstrap. Они написали, что они настолько вдохновлены CSSnext’ом, им это так понравилось, что Bootstrap 5 скорее всего будет на PostCSS (https://twitter.com/mdo/status/591364406816079873). Сейчас он на Less, потом он будет на Sass, а Sass они собираются выкидывать и переходить на PostCSS.
Т.е. что я хочу, чтобы вы сделали, когда пришли на этих выходных домой?
Первый момент: если вы делаете какой-то интересный инструмент для обработки CSS, подумайте о том, чтобы использовать PostCSS. PostCSS гораздо лучше, чем Regexp, потому что Regexp опасный – они изменяют вам карты кода и т.п. вещи.
Второй момент – препроцессоры. Вот, например, еще один перебежчик в наш лагерь – разработчик Grid’а, примеси для реализации сетки lost, который писал Макеев в очень интересном твиттере веб-стандартов, – он перешел на постпроцессоры, ему так понравилось, почему? Потому что раньше было нужно поддерживать три версии – одну для Stylus’а, одну для Less, другую для Sass. Это было очень нудно. А тут он понял: зачем это делать? Он просто возьмет как автопрефиксер. Он взял PostCSS, и его могут использовать пользователи Sass, пользователи Less и т.д.
Если вы делаете сайты, делаете инструмент и не используете PostCSS, добавьте автопрефиксер прямо сейчас. Это очень важно, почему? Потому что Google рекомендует единственный инструмент для работы с префиксами. Это только PostCSS, все остальные элементы гораздо хуже, есть много причин почему.
Третий момент. Если вы уже используете PostCSS, например, для автопрефиксера, посмотрите на другие плагины. Я советую начать с cssnext, потому что он реально клевый, это возможность писать на CSS 4 сейчас. Кроме этого, посмотрите список плагинов, мне кажется, что это понравится.
И четвертый момент. Если вы начинаете новый проект, я не рекомендую выкидывать Sass прямо сейчас, потому что PostCSS может работать хорошо и после Sass. Зачем его выкидывать? Если вы начинаете новый проект, подумайте, а зачем вам делать переменные, вложенности, примеси на препроцессорах. PostCSS тоже это имеет, если вы используете автопрофиксер, зачем вам парсить файл дважды? Просто добавьте переменные, вложенности, примеси в PostCSS перед вашим автопрефиксером.
Потому что IT же не про программирование, IT не про код. Потому что, по-хорошему, аську можно было сделать в телеграмме. Почему IT появилось сейчас? Потому что мы сейчас находимся в том времени, когда мы не можем решить задачи, стоящие перед нами. Все задачи, которые мы решаем сложнее, чем помещается в наш ум. В этом идея IT. IT – это борьба со сложностью. А что проще – два инструмента или один? По мне, так один.
Контакты
» Iskin
» Вконтакте
» Evil martians
Этот доклад — расшифровка одного из лучших выступлений на конференции фронтенд-разработчиков FrontendConf. Мы уже открыли подготовку к 2017 году, а подписавшись на список рассылки конференции Вы получите 8 лучших докладов прошлого года.
Самая сложная секция грядущей конференции HighLoad++ это "Производительность фронтенда". Фронтенд стал большим, это уже полноценный софт со своей архитектурой, моделями и данными (а не просто интерфейс, как было раньше). Именно в этом разрезе мы и изучаем его на этой секции.
Вот некоторые из планируемых докладов:
- Промышленное ускорение сайтов / Николай Мациевский (Айри.рф);
- Your hero images need you: Save the day with HTTP2 image loading / Tobias Baldauf (Akamai Technologies);
- The Accelerated Mobile Pages (AMP) Project: What lies ahead? / Paul Bakaus (Google);
Превышаем скоростные лимиты с Angular 2 / Алексей Охрименко (IPONWEB);
Instant Loading: Building offline-first Progressive Web Apps / Alex Russell (Google);
Комментарии (61)
P0WERMIC
22.09.2016 17:11+1Скорее бы CSS4 приняли и браузеры поддержали, тогда бы все эти пре-процессоры и пост-процессоры не нужны были бы в большинстве случаев.
gunlinux
23.09.2016 13:18CSS4 не выйдет простите. 4 — это версия определенного css модуля. То есть если вводится новый модуль его первая ревизия получит цифру 1. Если он расширяет возможности предыдущей версии например 3, то получит версию 4.
Таким образом, было принято решение, что для того, чтобы продолжать двигаться вперед, общую спецификацию CSS нужно разбить на множество отдельных спецификаций (модулей), каждый с собственным версионированием. Модули, расширяющие возможности, кото- рые уже присутствовали в CSS 2.1, переводились на уровень 3
Однако модули, посредством которых вводились совершенно новые концепции, начинали свою историю с уровня 1
http://w3.org/TR/css-flexbox-1
© Леа Веру — Секреты CSS. Еще был недавно доклад "Вы не знаете CSS", там много о стандартах было
k12th
22.09.2016 17:19Картинка про разницу — «в огороде бузина, в Киеве дядька».
Он хранит в себе базу данных Can I Use, пробегается по вашему CSS и находит, что например: «Чувак, ты мне сказал, что ты IЕ хочешь поддерживать, а user selected не поддерживается IE, ты точно уверен, что ты его должен был написать?». Это очень удобная вещь.
Какой в этом смысл? 99% что я специально написал это правило и специально пренебрег его поддержкой в IE — graceful degradation.
rtlcss
Почему это невозможно на sass и зачем там вообще sass, если вопрос решается так:
[dir="rtl"] a { right: 10px; text-align: right; }
Iskin
22.09.2016 19:14Давай-те объясню чуть точнее, как работает RTLCSS, чтобы было понятно, почему его нельзя сделать на Sass.
Вы пишите обычный код для обычного языка и даже не думаете об арабском:
.menu { left: 10px; text-align: left; }
Потом запускаете RTLCSS и он выдаёт отдельный файл для арабской локали, где будет:
.menu { right: 10px; text-align: right; }
То есть RTLCSS похож на Автопрефиксер — он сам находит нужный свойства в вашем CSS (те, которые специфичны для лево-право) и заменяет их на обратное значение.
В Sass у вас просто нет API для сканирования CSS, только то, что явно указал разработчик в качестве примеси (то есть придётся постоянно думать и легко забыть).raveclassic
22.09.2016 20:15Как быть, если мне в конкретном месте нужно оставить left без замены на right?
Iskin
22.09.2016 20:16Есть специальные управляющие комментарии, которыми можно выключить магию (выключить нужно гораздо реже)
k12th
22.09.2016 20:22Ну это получается что все равно надо везде пройтись ручками и отключить магию. Нет уж, я лучше примесь сделаю.
Iskin
22.09.2016 20:27Отключить вам нужно в 1—2 местах. А примесь использовать в сотне.
Практически все люди в Иране, которым я показывал RTLCSS были без ума от него — они явно отлично разбираются с практикой. Так же WordPress использует только RTLCSS и тоже отлично отзывались о её эффективности на CSSConf в Нью-Йорке.
Я понимаю, что часто хочешь взять что-то старое и не учить, но RTLCSS — «абсолютный хищник» в своей нише. Все кто занимается этим вопросов плотно высоко оценивают его полезность.k12th
22.09.2016 20:35Нет, я не боюсь учить новое — если оно мне кажется полезным и качественным.
Iskin
22.09.2016 20:37А почему вам RTLCSS не кажется качественным? Всё таки WordPress — огромный пользователь. ВКонтакте тоже собирается переходить на RTLCSS.
А почему вам кажется, что нужно будет выключать RTLCSS чаще, чем писать примесь? Может попробуйте на каком-нибудь маленьком тестовом проекте — вы тогда сразу прочувствуете как удобно стало.k12th
22.09.2016 20:47Ни вордпресс, ни вк как-то не имеют славу высокой инженерной культуры:)
Потому что я переводил пару интерфейсов на RTL, и там очень далеко не везде нужно было менять left на right и т.д.
Но вы правы, я попробую, когда будет возможность/необходимость.
Плюсик вам в карму за обоснованный евангелизм:)
k12th
22.09.2016 20:21Если я пишу обычный код и даже не думаю об i18n (а это не только RTL), то это плохо кончится в любом случае:) Создавать же отдельные css-файлы для каждой локали — вообще, мне кажется, за гранью.
Iskin
22.09.2016 20:23Понятно, что на практике иногда думать приходиться. Но, например, в репозитории проекта есть перевёрнутый сайт ГитХаба — весьма неплохо, большинство вещей сделано.
То есть думать придётся, но на порядок меньше.
Iskin
22.09.2016 20:25Для каждой локали не надо — один для обычных языков, второй файл для RTL-языков.
Вообще есть проект, который исправления RTLCSS не в отдельный файл переносит, а дописывает таким «патчем», как в вашем первом комментарии.
Но автор RTLCSS (он из Египта и постоянно занимается вопросом RTL) считает, что отдельный файл — проще. Всё равно сборка автоматизирована. Зато максимальная оптимизация по размеру и кол-ву запросов (но, опять же, если вы другого мнения это легко изменить — гибкость PostCSS позволяет).
vanxant
22.09.2016 21:12Почему, собственно, за гранью?
С переводом локали под готовый, существующий стиль вечные грабли: где-то фразы слишком длинные получаются, где-то слишком короткие. Соответственно, или сокращения прут из всех щелей, или наоборот «дырки» в дизайне появляются. Те же игры достаточно показательны в этом плане.
Понятно, что перевёрстывать всё целиком слишком трудоёмко. Но добавить отдельный файлик с селекторами вида html[lang=ru] <oldselector> {width: ...} — вполне нормальная практика для качественного перевода.
Iskin
22.09.2016 19:34Какой в этом смысл? 99% что я специально написал это правило и специально пренебрег его поддержкой в IE — graceful degradation.
Сейчас лучше всего этот плагин вызывать из Stylelint — там у вас будет спец. комментарий, чтобы явно указать, что вот в этой строчке всё в порядке — вы добавили graceful degradation. С такими явными комментариями и код понятнее (показано что это graceful degradation) и не получиться забыть где-то вставить продумать graceful degradation.
Scf
22.09.2016 18:27+1Ну вот, а я сам писал парсер CSS в AST для домашнего минимизатора имен классов. Быть может, перееду на PostCSS.
Holix
23.09.2016 17:18Да, тоже попытался, чтоб свой и без зависимостей сделать. Но из-за синтаксического бардака не стал. Мне хватило самописного токенизатора/детокенизатора с выбрасыванием комментариев/пробелов и оптимизацией единиц измерения и цветов. Серьезный парсер так и остался в планах.
PretorDH
22.09.2016 23:08А есть простое решение чтобы на лету парсить PostCSS на стороне клиента или сервера?
Iskin
23.09.2016 07:12Был плагин для Express. Но на стороне сервера не выгодно парсить динамически — проще один раз при деплое.
На стороне клиента можно запускать в теории, но готовое решение из коробки пока никто не сделал :(.PretorDH
23.09.2016 19:05Для применения в динамическом веб приложении обрабатывающем стили на лету другого пути нет.
Задамъ несколько вопросов:
— Насколько ядро специфично для оффлайн исполнения? Обёрточный клиентский скрипт вобще возможен без переписания ядра?
— Модули клонятся в приложение или можно удаленно затянуть прямо на сторону клиента?
— Генерациия префиксов на стороне клиента в идеале должна зависить от браузера? Нужно будет переписывать модуль (можно на лету фильтровать вашу базу Can i Use или есть возможность прописать настройки модуля)?Iskin
23.09.2016 19:09Краткий ответ: лучше используйте CSS-in-JS.
Моё самый любимый проект — JSS. Но ещё есть интересный CSJS, у которого есть Babel-плагин, способный запускать PostCSS перед сборкой JS на его стилях.
Так же есть postcss-js, чтобы использовать PostCSS уже в браузере для CSS-in-JS.PretorDH
23.09.2016 21:09«Удобный CSS-in-JS синтаксис» — не всегда годится.
У postcss-js уже есть objectifier.js, что для динамически созданых правил может частично помочь, но опять же «удобный CSS-in-JS синтаксис». Думалось о прямом парсинге текста PostCSS, а функции PostCSStoNode нет!
P.S. А так хотелось модулями еще HTML и JS код генерить в дополнение к CSS. Почему каждый проект на Node.js идет самым обходным путем? И делают все на половину или даже меньше. Как по мне то на ентом этапе «постпроцесинг» ничем не оличается от «препроцесинга». Разница чисто концептуальная. PostCSS пошли по той же дороге что и другие. Только SASS шел «спиной вперед» и спотыкался на каждом камне, а PostCSS «лицом» и переступает камни. В конце концов получили тот-же css-файл.
Iskin
23.09.2016 19:12Конкретно по вопросам:
1. Ядро написано для node.js, но специально не привязано к нему. Достаточно собрать его с помощью browserify или webpack и оно будет прекрасно работать в браузере.
2. Модули находятся в npm. Но это не проблема, поскольку легко решается с помощью browserify и webpack. Тот же webpack может грузить модули асинхронно.
3. Да, желательно написать новый Автопрефиксер, так как база данных Can I Use весьма большая, а смысла от неё мало. Но для большинства случаев можно один раз предкомпилировать стили при деплое, а на клиенте просто проставлять значения (не всегда будет работать, но в 99,9% случаев).
impwx
22.09.2016 23:29+4Человек, который писал транскрипт выступления, в некоторых местах не понял, о чем речь — поэтому «NP-библиотека» (к NP-задачам отношения не имеет, имелся в виду npm), «бесидж 3 кодирование» (которое на самом деле base64), и т.д.
Слово «стригифайр» тоже улыбнуло. Странно, что сам автор доклада говорит «не знаю, как перевести» — очевидно же, что это stringifier, т.е. функция, превращающая объект в строку.
phoenixweiss
22.09.2016 23:35Воу-воу, время, куда ты так неумолимо бежишь? Еще же вот только вчера казалось переходили на Sass как на нечто принципиально новое, и вот опять.
// Старческое брюзжание
Ronnie_Gardocki
23.09.2016 05:44+2Большая часть примеров «невозможно в sass» сильно притянута за уши. В половине случаев какие-то жуткие примеры того, чего бы я никогда не хотел увидеть в жизни, а в другой половине вещи которые лечатся парой тройкой миксинов или подрубанием готовых наборов миксинов.
Ну и самое главное, что со всеми этими плагинами каждый вася придумывает свои способы как написать вот это и так далее, в то время как в sass я точно знаю что это можно сделать вот так и вот так, и вернувшись к проекту через N месяцев я с легкостью пойму что тут нагородили, в отличии от кастомного плагина, который придется идти и изучать.
Давно уже читаю все эти статьи про «sass не нужен, давайте все юзать postcss», но из всех примеров видел пока только одну частично полезную вещь, это конструктор SVG в css (для bg-image) с помощью абстрактного синтаксиса (причем насколько я знаю его потом люди и на sass перетащили без проблем...).Iskin
23.09.2016 07:11Вы правы, что PostCSS даёт слишком много свободы и это иногда становится проблемой. Мне тоже нравятся не все плагины.
Но вы не правы, что «Sass хватает для всего». Препроцессор не равен всем CSS-инструментам. У нас есть очень много задач. Взять хотя бы тот же uncss (нахождение мёртвого CSS по статичному HTML) — полезно и совершенно нельзя сделать на Sass. Или Автопрефиксер. Или Stylelint. Или RCTLCSS.Ronnie_Gardocki
23.09.2016 07:32Ок, немного не так выразился.
Что мешает юзать PostCSS вместе с Sass, вместо того чтобы его хоронить каждый месяц? Я прекрасно понимаю что есть множество крутых плагинов, но полностью отказываться от sass, заменяя его зоопарком из плагинов (некоторые примеры выше прям вообще жуткие в этом плане) нет желания.Iskin
23.09.2016 07:34Ничего. Мы и не хороним Sass. Наоборот, советуем не уходить с Sass в старых проектах.
k12th
23.09.2016 10:59Если верить цифрам в табличке о производительности, то ничто не мешает выхлоп sass обрабатывать postcss-ом, который работает на два порядка быстрее (не считая libsass, но мы же в приличном месте).
Непонятно, правда, сколько и каких postcss-плагинов участвовало в том тесте…
Iskin
23.09.2016 11:38В тесте плагин на переменные, вложенность, математику, примеси — такой самый популярный набор
Akuma
23.09.2016 10:53+2Интересно конечно. Но как решается проблема подсветки синтаксиса в IDE?
Для LESS есть отдельное расширение файлов — .less
Мой PhpStrom знает его синтаксис и ни на что не ругается.
А если я в обычных CSS файлах начну писать какие-то новые, нестандартные селекторы — IDE мне пальцем у виска начнет крутить. Можно конечно отключить все это, но зачем?k12th
23.09.2016 11:01Мне посоветовали использовать другое расширение (скажем, *.sss) и добавить его в список расширений для типа файлов LESS. Но я не пробовал.
Iskin
23.09.2016 11:40Если плагины не меняют синтаксис (Автопрефиксер, RTLCSS), то подсветка не нужна.
Для Stylelint есть подсветка ошибок для Atom и Sublime.
Если вы используете препроцессор PreCSS (который на основе PostCSS-плагинов), то ставьте расширение .pcss — подсветка есть для Atom, Sublime, IDE от JetBrains.Akuma
23.09.2016 12:02Автопрефиксер можно прикрутить и после LESS/SASS — у меня прекрасно работает.
RTLCSS — нужен очень немногим, если брать широкую аудиторию обычных разработчиков. Да и его можно так же просто прикрутить.
Если я использую препроцессор, то зачем мне его менять с моего текущего? Все равно 99% функционала одинаковые. Даже различия между LESS и SASS не все разработчики могут назвать (кроме синтаксиса).
Я это к тому, что между PostCSS и препроцессорами нет существенной разницы. Либо ее никто не смог до сих пор внятно объяснить: во всех подобных статьях возникает куча вопросов «А зачем?».
Например, Webpack сразу потестил Grunt и Gulp именно за счет нововведений вроде поддержки импорта, webpack-dev-server и прочих плюшек. В остальном же он делает все то же самое.
PostCSS же в данном случае просто делает все то же самое и не дает ничего нового.
Исключительно мое мнение. Поклонники PostCSS — не воспринимайте слишком близко к сердцу :)Iskin
23.09.2016 12:17Вы правы, что PreCSS (не PostCSS, а конкретный набор плагин для решения одной задачи) не имеет ничего нового относительно Sass.
Но то что вы сравниваете PostCSS с Sass — совсем неправильно. PostCSS — фреймворк для создания любых CSS-инструментов. Препроцессор — только одна из множества этих инструментов.
Вы полностью правы, если вы уже используете препроцессор, который не построен на PostCSS — то вам не надо переходить на препроцессор PreCSS на базе PostCSS. Мы об этом как раз и говорим (это запись выступления годичной давности).
Но если вы начинаете новый проект и уже используете кучу инструментов на базе PostCSS? Тут у PreCSS появляется главный смысл — чтобы все инструменты были построены на одной фреймворке (PostCSS). В итоге у вас и быстрее сборка (PostCSS один раз парсит и все инструменты уже работают с готовым AST). Между инструментами гарантировано нет конфликтов. Унификация — это всегда круто.
develop7
23.09.2016 16:31Для https://www.jetbrains.com/support/eap/ в репозитории есть плагин с поддержкой PostCSS
onecomment
23.09.2016 13:19+6Iskin
23.09.2016 19:13Да ладно, про Babel или про Sass больше разговоров. Просто у меня в ТвитДеске идёт живой поиск твитов про PostCSS и я всегд влажу в разговор, если его вижу.
Holix
23.09.2016 13:19Ну всё, довод про скорость меня убедил. Завтра же попробую это вписать в свою систему сборки.
AlgenGold
23.09.2016 13:19-1Так и не понял в чем преимущество этой приблуды. Sass не умеет ставить автопрефиксы… да и не надо. Как правило sass сам по себе не компилируется, один из вариантов это использование taskrunner'ов. Берем какой-нить gulp и в таску добавляем автопрефиксер, на выходе получаем годный css со всеми префиксами до 3 колена. Css тут можно обработать насколько фантазии хватит. И плагинов тут огромное множество!
Iskin
23.09.2016 19:21+6Это транскрипт старого выступления (я бы его не выкладывал), давай-те я попробую объяснить лучше, чем у меня получалось тогда.
PostCSS — это фреймворк для разработки CSS-инструментов.
Вот у вас есть крутая идея минификатора CSS. Или вы хотите написать новые препроцессор. Или вы увидели крутой черновик спецификации и хотите написать полифил. Для всего этого вам нужен парсер, генератор карт-кода, инструменты разработки, обвязка для Grunt, Gulp, webpack.
PostCSS, как раз даёт всё это — парсер, генератор карт кода, инструменты разработчика, обвязки для сборщиков.
Но когда несколько инструментов начинают использовать один парсер PostCSS, получается огромный выигрыш от унификации:
Сейчас у вас Sass парсит исходник, генерирует CSS. Минификатор снова парсит строку. Прасинг — самый долгий процесс в работе CSS-инструментов. Если все инструменты будут использовать один парсер, то зачем нам парсить на каждом шаге — парсим один раз в начале, а между плагинами передаём отпарсенное дерево.
Кроме того, унификация даёт ещё пару плюсов. Все инструменты становятся совместимы между собой (линтер не будет падать от синтаксиса «CSS4» вашего полифила). Инструмент созданный для одного проекта (парсер битого CSS или вывод ошибки в браузер) становится доступен всем инструментам.
Собственно в этом и смысл PostCSS. Это платформа для создания новых CSS-инструментов. Чем больше у вас инструментов основанных на PostCSS, тем больше плюсов вы получаете от унификации.KaminskyIlya
26.09.2016 10:19+2Вот у вас есть крутая идея минификатора CSS.
Есть такая идея. Прошу меня извинить за небольшой офтоп…
Вот честно говоря, сомнительно, что PostCSS «не приседая со штангой» сможет построить правильную синтаксическую модель CSS. Дело в том, что стандарт CSS 2/3/4 — это уже настолько сложный и запутанный документ, что обычными регулярками его не распарсишь.
Чего только стоят синтаксис селекторов, квалификаторов, выражений медиа-запросов (@media), и формат условных запросов (@conditional),… если внимательно почитать документацию.
Ну вот для примера.
Знаете ли вы, что вот эта конструкция является валидным именем класса:
.data\\\{5\} {… }
А как вам такой селектор по атрибуту:
[my|src^="/icon/"]
Или вот еще простенький квалификатор:
.colorized[ href
]:NOT(
.blue.dark.orange
)
А может быть такой селектор:
*|P * .test + P > span ~ em {...}
Или вот еще, финт со строками:
a::before
{
content: 'Этот текст слишком длинный\
так что я пожалуй перенесу \0000A \U+0003F #&567; его на следующую строку'
}
Ах, да, вот еще можно так:
.class { background-image: url(/my_url:;-.png) }
А еще добавьте к этому всему esape-последовательности, unicode-символы, инструкцию charset (которая прикажет нам сменить кодировку файла на лету), и т.п. и т.п. И все это парсер CSS должен поддерживать.
Кому интересно, вот несколько ссылок про CSS стандарт.
http://www.w3.org/TR/css-syntax-3/
http://www.w3.org/TR/css3-selectors/
http://www.w3.org/TR/css3-webfonts/
http://www.w3.org/TR/css-fonts-3/
http://www.w3.org/TR/css3-animations/
http://www.w3.org/TR/css3-values/
http://www.w3.org/TR/css3-color/
http://www.w3.org/TR/css3-namespace/
https://www.w3.org/TR/css3-images/
http://www.w3.org/TR/css3-mediaqueries/
http://www.w3.org/TR/css3-conditional/
http://www.w3.org/TR/css-ui-3/
http://www.w3.org/TR/css-counter-styles-3/
http://www.w3.org/TR/css-flexbox-1/
http://www.w3.org/TR/css-masking-1/
http://www.w3.org/TR/css-shapes-1/
http://www.w3.org/TR/css-writing-modes-3/
И это только 3-й.
Может быть поэтому PostCSS и уделывает других за счет того, что слишком упрощенно подходит к анализу файлов?Iskin
26.09.2016 13:34Привет. Отличный вопрос! Да, ты прав. Написать универсальных парсер всех структур CSS очень сложно.
Кроме того тех проблем, что ты указал (куча спецификаций) есть ещё более большая — а как делать полифилы или расширения CSS типа CSS Modules?
Поэтому у PostCSS специально чуть другая философия. На самом деле парсинг состоит из 2 частей — разбор «грамматики» и разбор «смысла». Вот если мы парсим «Вилкой удобно есть суп». Когда мы «парсим» грамматику, мы только определяем, где подлежащие, сказуемое и т. д. Но мы не пытаемся понять конкретный смысл фразы. Потом мы уже по грамматике можем отпарсить смысл, взяв данные по отношению вилки, супа и т. п. (тут бы мы заметили ошибку смысла, так как вилкой не удобно есть суп).
Тоже самое и в PostCSS. Она парсит только структуру CSS, но не смысл конкретных выражений. Конкретно мы используем эту спецификацию https://www.w3.org/TR/css-syntax-3/
Если разработчикам плагинов нужен смысл каких-то блоков — они могут использовать специальные допарсеры — postcss-selector-parser, postcss-value-parser и т. п.
Есть и другой подход — например, csstree парсит всё целиком.
Но, как я уже писал, на полном парсере (которые будет всё проверять) не написать огромное количество очень нужных CSS-инструментов. Так что такой подход просто не подходит для целей PostCSS.
Iskin
26.09.2016 13:39Может быть поэтому PostCSS и уделывает других за счет того, что слишком упрощенно подходит к анализу файлов?
Не совсем. Многие парсеры в нашем бенчмарке парсят тоже очень приближенно. С другой стороны, csstree парсит всё, как вы хотите, но даже быстрее PostCSS.
На самом деле, практически весь вопрос скорости парсинга — это токенайзер. Оптимизировать имеет смысл только его. Если парсить всё, то токенов, конечно, будет больше — но не принципиально. Все эти проверки и разбор спецификаций в основном будет происходить уже после токеном. А по моему опыту, что ты будешь делать после токенов уже не особо важно с отношении скорости.
DenVdmj
26.09.2016 14:59Помню, что когда ознакомился с плагинописанием под postCSS, некоторые вещи мне показались не очень красивыми. Поскольку это было относительно давно, просто положу здесь пост, написанный по горячему:
------------------
У PostCSS куцый AST, и то, что плагинам приходится «парсить» декларации вручную — имхо, большое зло. В кавычках слово «парсить» не случайно, разве можно назвать парсингом тупую регулярку? Регулярка вида /\b(\w+)\(/ — это в лучшем случае, в основном в плагинах юзают indexOf. Все это выливается в то, что практически все плагины, которые «расширяют» синтаксис деклараций или вводят функции, ломаются на подобном css-коде (или портят его)
.cssclass1 { content: "-=)some(=-" } .cssclass1 { content: "MyOwnSuperDuperFunction(param)" }
Я понимаю, что вероятность подобного кода исчезающе мала, но я не доверяю решениям которые, не то что не имеют защиты от дурака, но полагаются на строго определенные юзкейсы.
По факту, никто не хочет писать полноценный парсинг деклараций, тем более, что это просто дико писать полноценный корректный парсер для каждого плагина, — зачем, тогда, спрашивается, вообще, нам готовый AST?
Я бы предпочел иметь в плагинах более детальный AST, а это значит, что нужен «синтаксис будущего», по крайней мере некий более определенный синтаксис.Holix
27.09.2016 16:52Абсолютно согласен. Являясь любителем поизобретать велосипеды как-то задумал написать парсер CSS с целью дальнейшей оптимизации. И столкнулся как раз тем же. Жуткий синтаксический бардак. Токенизатор должен слегка разбираться в синтаксисе, чтоб работать однозначно. Очень много ненужного. Такое впечатление, что это плод коллективного творчества. К имеющимся конструкциям прикручивают и прикручивают уродства. Т.е. изначальная идея была проста и практична, но то-что пытаются из CSS выжать сейчас — это даже эпичнее, чем апгрейд C в C++.
token
Что то наверное я слишком старым стал, не понимаю зачем все это нужно.
nerumb
Ответ прост, все ради простоты =)
Iskin
1. Чтобы был универсальный фреймворк для создания CSS-инструментов (PostCSS), так что инструменты будет легче делать
2. Чтобы все CSS-инструменты строились на основе одного фреймворка — переиспользовали больше кода, меньше конфликтовали
vitvad
здесь уместно вставить картинку стандарты.jpg
мне кажется, все кто пользовался css-препроцессорами продолжат ими пользоваться.
PostCSS это для староверов, которые не захотели писать less/sass/etc. или им чем-то не нравились эти инструменты, а тут им тот же css, но теперь со вкусом клубники: с автодополнениями, префиксами и причесыванием.
Iskin
Я согласен, что PostCSS не захватил все ниши. Но у вас есть логическая ошибка — вы думаете, что CSS-инструмент = препроцессору.
На самом деле PostCSS стал самый популярным CSS-парсером уже, котрый загружается с npm — графики.
Причина в том, что PostCSS используется в куче новых CSS-инструментов, которые не являются препроцессорами. CSS Modules, css-loader в webpack, Stylelint, Autoprefixer, cssnano, uncss, RTLCSS.
SVGen
В зависимости от используемых модулей синтаксис
pcss
может серьёзно отличаться от «чистых» стилей.А может и не.
Сасс, лесс, стайлус это готовые наборы обработчиков, изменить или добавить новые сложно.
PostCSS
— платформа для создания своего набора обработчиков. Можно написать их все самостоятельно или выбрать из множества готовых. В статье перечислена лишь малая часть уникальных возможностей, которые появляются благодаря доступу к результату работы парсера.В общем, сфера применения
PostCSS
гораздо шире.[Перешёл со стайлуса, всем доволен :]