Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Сегодня публикуем вторую часть перевода материала о борьбе с неиспользуемым CSS-кодом.
→ Первая часть
Предположим, в некоем проекте CSS пишут с использованием Less или Sass, а затем, для компиляции имеющегося кода в обычный CSS, применяют постпроцессор. В таком проекте, вероятно, имеется автоматическая система избавления от неиспользуемого CSS, которая запускается после выполнения препроцессинга CSS. Выглядеть подобное может так:
Это, с одной стороны, имеет смысл, а с другой — выглядит в моих глазах немного странным. Речь идёт о том, что при таком подходе не производится исправления исходного кода, содержащего команды стилизации, на основе которого создаётся итоговый CSS-код, в который входит и неиспользуемый CSS. Вместо этого ненужный CSS просто убирают в конце процесса сборки проекта. Подозреваю, что в JavaScript, при реализации алгоритма tree-shaking, нечто подобное делается уже довольно давно. То есть, подобное обращение с CSS — это совсем не новость. Но мне это, всё равно, кажется неправильным, так как кодовая база CSS — это то, что, можно сказать, лежит на поверхности веб-проектов. Такой подход почти что подталкивает разработчиков к небрежному написанию CSS, к тому, чтобы сваливать в исходный CSS-код всё попало. И правда — от ненужного CSS система избавится автоматически. Но это совершенно лишает разработчиков стремления понять то, как именно стилизуются их проекты, как именно в них используется CSS.
PurgeCSS — это ещё один проект, который направлен на борьбу с неиспользуемым CSS. Хотя это и не относится напрямую к возможностям этого проекта, но он мне нравится тем, что в его документации чётко разъяснены его отличия от конкурентов. Выше мы уже приводили фрагмент сравнения PurgeCSS и PurifyCSS. А вот — ещё одно извлечение из документации PurgeCSS, посвящённое PurifyCSS. Речь идёт о том, что главная проблема PurifyCSS заключается в низком уровне модульности этого проекта. Однако в этом кроется и основная сильная черта PurifyCSS. Как уже было сказано, PurifyCSS считает CSS-селекторами все слова, находимые им в файлах. Такой подход чреват ошибками. Но PurifyCSS решает эту проблему, давая возможность создавать функции-экстракторы. Такая функция принимает содержимое файла и извлекает из него список используемых в нём CSS-селекторов. Это позволяет очень хорошо решить задачу избавления от неиспользуемого CSS-кода.
Сейчас проект PurgeCSS выглядит крупным игроком рынка средств для очистки CSS-кода. Многие им пользуются, многие пишут о нём.
Несмотря на то, что PurgeCSS для работы с Tailwind нуждается в особой настройке, возникает такое ощущение, что два эти инструмента отлично друг с другом сочетаются. На самом деле, даже в документации Tailwind можно найти рекомендацию по их совместному использованию. А у PurgeCSS есть инструмент командной строки для применения его в процессе сборки проектов.
Я так думаю, что суть этого сводится к следующему: Tailwind создаёт большой CSS-файл, полный вспомогательных селекторов. Но не предполагается, что в проекте будут использованы все эти селекторы. Разработчик применяет их для решения всех задач по стилизации своего HTML-кода, а затем PurgeCSS анализирует этот HTML-код и убирает ненужные селекторы, формируя готовый к продакшну CSS.
Правда, до PurgeCSS ещё нужно донести сведения о каждом HTML и JavaScript-файле, используемом на сайте. Другими словами — нужно самостоятельно настроить всё, что имеет отношение к внешним ресурсам, и учитывать то, что данные, поступающие в проект из неких хранилищ, вероятно, не смогут быть проанализированы в ходе сборки проекта. В результате использование PurgeCSS при сборке проектов предполагает немалый объём ручной работы.
Мне больше всего нравится следующий подход к удалению ненужного CSS. Он заключается в том, чтобы в команде разработчиков проекта был бы кто-то, кто очень хорошо знаком с CSS-кодом этого проекта. Этот человек должен быть в курсе текущих проблем со стилями и должен постепенно их решать. Возможно, это устаревший взгляд на ситуацию, принадлежащий человеку, которому стоило бы идти в ногу со временем. Но мне это, в любом случае, кажется наиболее практичным подходом. Учитывая то, что рассматриваемую нами задачу так тяжело решить, я думаю, что ответом на тот вызов, который бросает эта задача разработчикам, может стать тяжёлый труд. Ответ — это понимание проблемы и её постепенное решение. Решить эту задачу может фронтенд-разработчик, который близко знаком с проектом и знает о том, что в нём используется, а что — нет.
Я видел один экстремальный подход к выяснению того, используется ли на сайте некий селектор. В CSS-блоке применялась конструкция наподобие
Но, возможно, мой любимый инструмент в наборе средств исследователя неиспользуемого CSS это тот, о котором речь пойдёт в следующем разделе.
Этот метод заключается в том, что разработчик делает как можно больше скриншотов сайта. Делаются копии экранов самых важных страниц, и тех страниц, вид которых зависит от состояния приложения. Скриншоты делаются в разных браузерах, при разных размерах экрана. Эти скриншоты создаются на основе материалов ветки
Затем, прежде чем объединить с веткой
Собственно говоря, вот видео, в котором это показано.
Надо отметить, что на тему инструментов для исследования визуальной регрессии сказано уже очень много всего, но именно автор этого видео — это единственный человек, который разъяснил всё предельно доходчиво. Нужно не просто делать скриншоты; нужно их сравнивать и искать различия между ними. Нужно не просто находить различия; нужно их принимать или отклонять. Кроме того, надо, чтобы принятие или одобрение изменений влияло бы на процесс слияния веток в репозиториях. Кроме того, у разработчика должна быть возможность настройки браузера перед снятием копии экрана и возможность автоматизации работы со сделанными скриншотами.
Я уверен в том, что многие из читателей этого материала могут сказать: «У меня нет неиспользуемого CSS, так как применяемые мной инструменты генерируют в точности тот код, который мне нужен, и ничего больше».
Если так — то это просто замечательно.
Возможно, речь идёт об Atomizer. Возможно — это инструмент Tachyons, результаты работы которого пропускают через UnCSS и соблюдают при этом повышенную осторожность. Может — это комбинация Tailwind + PurgeCSS, которая сейчас у всех на слуху.
Может — со стилями работают ещё как-нибудь. Если некто тесно связывает JavaScript-компоненты и стили, скажем, как при использовании React и Emotion, или даже просто применяет CSS-модули с чем бы то ни было, среди преимуществ таких вот СSS-in-JS-подходов можно отметить уменьшение объёма неиспользуемого CSS в готовых проектах. Кроме того, так как при сборке многих проектов, основанных на JavaScript, применяются реализации алгоритма tree-shaking и техники разделения кода, в таких проектах не только будет меньше ненужного CSS. В ходе их работы загружаться будет только то, что нужно в каждой конкретной ситуации. Но, конечно, недостатки есть и у подобных подходов к работе с CSS.
Давайте теперь подумаем о том, как избежать появления ненужного CSS-кода в наших будущих проектах. Я полагаю, что будущее стилизации — это разделение между глобальными стилями, и стилями, применяемыми к отдельным компонентам. Большинство стилей ограничено рамками компонентов, но есть и глобальные стили, благодаря использованию которых можно задействовать каскадную природу CSS. Например — это может быть нечто вроде глобальных стандартных настроек типографического характера.
Если большинство стилей ограничено рамками компонентов, то я думаю, что у ненужных стилей меньше шансов проникнуть в готовые проекты, так как разработчику несложно вникнуть во взаимоотношения небольших и тесно связанных фрагментов HTML и CSS. А когда компонент убирают из проекта или развивают, стилизация покидает проект или развивается вместе с ним. В результате CSS-сборки создаются на основе реально используемых в проекте компонентов.
Технологии CSS-in-JS совершенно естественным образом двигаются в этом направлении. При применении таких технологий стили привязаны к компонентам. А это в данном случае самое главное. Но привязка стилей к компонентам — это необязательно. Мне нравится универсальный подход, подразумевающий использование CSS-модулей. Он практически полностью нацелен на разделение областей действия стилей и не заставляет разработчика пользоваться каким-то конкретным JavaScript-фреймворком.
Может быть, всё вышесказанное кажется вам чем-то теоретическим или далёким от реальных нужд веб-разработчиков. У вас просто есть сайт, на котором используется Bootstrap, и вам хотелось бы уменьшить размер CSS, который загружается пользователями этого сайта. Если так — я посоветовал бы вам пользоваться исходным кодом Bootstrap, а не его стандартной сборкой. Этот исходный код написан с использованием SCSS и состоит из множества подключаемых модулей. А это значит, что если вам некоторые части Bootstrap не нужны — соответствующие модули можно просто отключить.
Удаление модулей dropdowns, badges и breadcrumbs из Bootstrap перед сборкой проекта
Желаю всем удачи в нелёгкой борьбе с ненужным CSS-кодом.
Уважаемые читатели! Как вы боретесь с неиспользуемым CSS-кодом, который попадает в продакшн?
→ Первая часть
Постпроцессинг CSS
Предположим, в некоем проекте CSS пишут с использованием Less или Sass, а затем, для компиляции имеющегося кода в обычный CSS, применяют постпроцессор. В таком проекте, вероятно, имеется автоматическая система избавления от неиспользуемого CSS, которая запускается после выполнения препроцессинга CSS. Выглядеть подобное может так:
- Sass.
- PostCSS / автоматическая система работы с префиксами.
- Удаление неиспользуемого CSS.
- CSS-код, готовый для продакшна.
Это, с одной стороны, имеет смысл, а с другой — выглядит в моих глазах немного странным. Речь идёт о том, что при таком подходе не производится исправления исходного кода, содержащего команды стилизации, на основе которого создаётся итоговый CSS-код, в который входит и неиспользуемый CSS. Вместо этого ненужный CSS просто убирают в конце процесса сборки проекта. Подозреваю, что в JavaScript, при реализации алгоритма tree-shaking, нечто подобное делается уже довольно давно. То есть, подобное обращение с CSS — это совсем не новость. Но мне это, всё равно, кажется неправильным, так как кодовая база CSS — это то, что, можно сказать, лежит на поверхности веб-проектов. Такой подход почти что подталкивает разработчиков к небрежному написанию CSS, к тому, чтобы сваливать в исходный CSS-код всё попало. И правда — от ненужного CSS система избавится автоматически. Но это совершенно лишает разработчиков стремления понять то, как именно стилизуются их проекты, как именно в них используется CSS.
PurgeCSS
PurgeCSS — это ещё один проект, который направлен на борьбу с неиспользуемым CSS. Хотя это и не относится напрямую к возможностям этого проекта, но он мне нравится тем, что в его документации чётко разъяснены его отличия от конкурентов. Выше мы уже приводили фрагмент сравнения PurgeCSS и PurifyCSS. А вот — ещё одно извлечение из документации PurgeCSS, посвящённое PurifyCSS. Речь идёт о том, что главная проблема PurifyCSS заключается в низком уровне модульности этого проекта. Однако в этом кроется и основная сильная черта PurifyCSS. Как уже было сказано, PurifyCSS считает CSS-селекторами все слова, находимые им в файлах. Такой подход чреват ошибками. Но PurifyCSS решает эту проблему, давая возможность создавать функции-экстракторы. Такая функция принимает содержимое файла и извлекает из него список используемых в нём CSS-селекторов. Это позволяет очень хорошо решить задачу избавления от неиспользуемого CSS-кода.
Сейчас проект PurgeCSS выглядит крупным игроком рынка средств для очистки CSS-кода. Многие им пользуются, многие пишут о нём.
- Вот материал о том, как пользоваться PurgeCSS, в частности — при работе с Bootstrap.
- Из этой статьи можно узнать о том, что PurgeCSS не удалят селекторы в необычных обстоятельствах с использованием белых списков.
- Здесь можно узнать о том, как PurgeCSS используют в связке с npm-скриптами и с PostCSS.
- Тут написано о том, как PurgeCSS работает с Tailwind.
Несмотря на то, что PurgeCSS для работы с Tailwind нуждается в особой настройке, возникает такое ощущение, что два эти инструмента отлично друг с другом сочетаются. На самом деле, даже в документации Tailwind можно найти рекомендацию по их совместному использованию. А у PurgeCSS есть инструмент командной строки для применения его в процессе сборки проектов.
Я так думаю, что суть этого сводится к следующему: Tailwind создаёт большой CSS-файл, полный вспомогательных селекторов. Но не предполагается, что в проекте будут использованы все эти селекторы. Разработчик применяет их для решения всех задач по стилизации своего HTML-кода, а затем PurgeCSS анализирует этот HTML-код и убирает ненужные селекторы, формируя готовый к продакшну CSS.
Правда, до PurgeCSS ещё нужно донести сведения о каждом HTML и JavaScript-файле, используемом на сайте. Другими словами — нужно самостоятельно настроить всё, что имеет отношение к внешним ресурсам, и учитывать то, что данные, поступающие в проект из неких хранилищ, вероятно, не смогут быть проанализированы в ходе сборки проекта. В результате использование PurgeCSS при сборке проектов предполагает немалый объём ручной работы.
Мой любимый подход к избавлению от неиспользуемого CSS
Мне больше всего нравится следующий подход к удалению ненужного CSS. Он заключается в том, чтобы в команде разработчиков проекта был бы кто-то, кто очень хорошо знаком с CSS-кодом этого проекта. Этот человек должен быть в курсе текущих проблем со стилями и должен постепенно их решать. Возможно, это устаревший взгляд на ситуацию, принадлежащий человеку, которому стоило бы идти в ногу со временем. Но мне это, в любом случае, кажется наиболее практичным подходом. Учитывая то, что рассматриваемую нами задачу так тяжело решить, я думаю, что ответом на тот вызов, который бросает эта задача разработчикам, может стать тяжёлый труд. Ответ — это понимание проблемы и её постепенное решение. Решить эту задачу может фронтенд-разработчик, который близко знаком с проектом и знает о том, что в нём используется, а что — нет.
Я видел один экстремальный подход к выяснению того, используется ли на сайте некий селектор. В CSS-блоке применялась конструкция наподобие
background-image: url(/is-this-being-used.gif?selector);
. После её применения периодически проверялись серверные логи для того, чтобы выяснить, был ли сделан запрос на получение соответствующего изображения. Если такой запрос был — значит исследуемый блок CSS используется. Если не было — значит не используется.Но, возможно, мой любимый инструмент в наборе средств исследователя неиспользуемого CSS это тот, о котором речь пойдёт в следующем разделе.
Исследование проектов методом визуальной регрессии
Этот метод заключается в том, что разработчик делает как можно больше скриншотов сайта. Делаются копии экранов самых важных страниц, и тех страниц, вид которых зависит от состояния приложения. Скриншоты делаются в разных браузерах, при разных размерах экрана. Эти скриншоты создаются на основе материалов ветки
master
репозитория проекта.Затем, прежде чем объединить с веткой
master
любую другую ветку, создаются новые скриншоты, сделанные на основе материалов новой ветки, и сравниваются с теми, что были сделаны для ветки master
. Это, конечно, делается не вручную, а программным способом.Собственно говоря, вот видео, в котором это показано.
Надо отметить, что на тему инструментов для исследования визуальной регрессии сказано уже очень много всего, но именно автор этого видео — это единственный человек, который разъяснил всё предельно доходчиво. Нужно не просто делать скриншоты; нужно их сравнивать и искать различия между ними. Нужно не просто находить различия; нужно их принимать или отклонять. Кроме того, надо, чтобы принятие или одобрение изменений влияло бы на процесс слияния веток в репозиториях. Кроме того, у разработчика должна быть возможность настройки браузера перед снятием копии экрана и возможность автоматизации работы со сделанными скриншотами.
Atomic CSS и CSS-in-JS
Я уверен в том, что многие из читателей этого материала могут сказать: «У меня нет неиспользуемого CSS, так как применяемые мной инструменты генерируют в точности тот код, который мне нужен, и ничего больше».
Если так — то это просто замечательно.
Возможно, речь идёт об Atomizer. Возможно — это инструмент Tachyons, результаты работы которого пропускают через UnCSS и соблюдают при этом повышенную осторожность. Может — это комбинация Tailwind + PurgeCSS, которая сейчас у всех на слуху.
Может — со стилями работают ещё как-нибудь. Если некто тесно связывает JavaScript-компоненты и стили, скажем, как при использовании React и Emotion, или даже просто применяет CSS-модули с чем бы то ни было, среди преимуществ таких вот СSS-in-JS-подходов можно отметить уменьшение объёма неиспользуемого CSS в готовых проектах. Кроме того, так как при сборке многих проектов, основанных на JavaScript, применяются реализации алгоритма tree-shaking и техники разделения кода, в таких проектах не только будет меньше ненужного CSS. В ходе их работы загружаться будет только то, что нужно в каждой конкретной ситуации. Но, конечно, недостатки есть и у подобных подходов к работе с CSS.
Итоги
Давайте теперь подумаем о том, как избежать появления ненужного CSS-кода в наших будущих проектах. Я полагаю, что будущее стилизации — это разделение между глобальными стилями, и стилями, применяемыми к отдельным компонентам. Большинство стилей ограничено рамками компонентов, но есть и глобальные стили, благодаря использованию которых можно задействовать каскадную природу CSS. Например — это может быть нечто вроде глобальных стандартных настроек типографического характера.
Если большинство стилей ограничено рамками компонентов, то я думаю, что у ненужных стилей меньше шансов проникнуть в готовые проекты, так как разработчику несложно вникнуть во взаимоотношения небольших и тесно связанных фрагментов HTML и CSS. А когда компонент убирают из проекта или развивают, стилизация покидает проект или развивается вместе с ним. В результате CSS-сборки создаются на основе реально используемых в проекте компонентов.
Технологии CSS-in-JS совершенно естественным образом двигаются в этом направлении. При применении таких технологий стили привязаны к компонентам. А это в данном случае самое главное. Но привязка стилей к компонентам — это необязательно. Мне нравится универсальный подход, подразумевающий использование CSS-модулей. Он практически полностью нацелен на разделение областей действия стилей и не заставляет разработчика пользоваться каким-то конкретным JavaScript-фреймворком.
Может быть, всё вышесказанное кажется вам чем-то теоретическим или далёким от реальных нужд веб-разработчиков. У вас просто есть сайт, на котором используется Bootstrap, и вам хотелось бы уменьшить размер CSS, который загружается пользователями этого сайта. Если так — я посоветовал бы вам пользоваться исходным кодом Bootstrap, а не его стандартной сборкой. Этот исходный код написан с использованием SCSS и состоит из множества подключаемых модулей. А это значит, что если вам некоторые части Bootstrap не нужны — соответствующие модули можно просто отключить.
Удаление модулей dropdowns, badges и breadcrumbs из Bootstrap перед сборкой проекта
Желаю всем удачи в нелёгкой борьбе с ненужным CSS-кодом.
Уважаемые читатели! Как вы боретесь с неиспользуемым CSS-кодом, который попадает в продакшн?