Много лет назад я мечтал о временах, когда хороший интернет войдет в каждый дом. И он пришел, а вслед за ним - мобильный интернет. Борьба за колибайтики продолжается.
Чем больше лет проекту, чем больше итераций редизайна он пережил - тем больше его кодовая база. Разбиение CSS на модули, компонентные стили, хорошая архитектура frontend составляющей - если все это прошло мимо вас, дочитайте до конца, возможно мои мысли покажутся вам разумными.
Итак, ваш CSS стал громоздким и вы подозреваете что далеко не весь код реально нужен?
Это произошло и со мной. Я начал искать инструмент, который бы мог показать мне какой CSS код используется в проекте, а какой остался от старых итераций разработки. Первым делом подумалось об uncss от Giacomo Martino. Но, как оказалось, он не очень пригоден для использования на большом проекте с большим количеством страниц, скрытых разделов, авторизациях и прочих штуках, которые зависят от поведения пользователя. Одно дело собрать CSS с нескольких HTML страниц, а совсем другое из работающего интернет магазина с личным кабинетом и внешним видом, зависящем от поведения пользователя.
В uncss использован простой подход - собрать все селекторы и проверить их на существование через document.querySelector
. Просто и со вкусом. Но, как повторить все действия пользователя и не пропустить ни одной страницы?
В твиттере Веб-стандартов публиковалась статья Finding Dead CSS Harry Roberts в которой предлагалось маркировать потенциально неиспользуемы CSS код при помощи CSS свойства background-image
:
1 | #checkout_wrapper { |
и ждать. После определенного времени предлагалось проверить access_log
файл на наличие в нем строки, содержащей checkout_wrapper.gif
что означало бы тот факт, что CSS селектор жив и используется. В противном случае - селектор следует удалить из CSS.
Очевидно, что такой подход не очень эффективвен при большом количестве CSS, требует много времени, а самое главное - подразумевает тот факт, что нам известно о потенциально неиспользуемых компонентах и блоках. Но сама идея о том, что можно пассивно собирать информацию об используемых CSS селекторах - прекрасна.
А что если соединить идеи uncss и Harry Roberts? Что для этого понадобится?
получить все селекторы из всех существующих CSS файлов проекта
передать их реальным посетителям проекта
обработать селекторы на JS, отфильтровать их, оставив только используемые на странице
передать отфильтрованные селекторы на сервер для накопления информации
через время обработать существующие CSS на основании накопленной информации
Как получить все селекторы? Работать с CSS как с текстом не удобно, эффективнее получить AST при помощи reworkcss и работать с деревом.
1 | const css = require('css') |
Полученые таким образом селекторы сохраняем в JSON файл и отдаем посетителям сайта. На стороне сайта проверяем существование каждого селектора на странице при помощи document.querySelector
, а результат с отфильтрованными селекторами отдаем обратно на сервер и сохраняем (например, в базу данных).
Основную работу выполняет пользователь сайта и его браузер. Нам остается лишь ждать пока накопится достаточное количество данных и на основании этих данных очистить существующие CSS проекта.
В моем случае удалось уменьшить CSS со 156кб до 55кб. При этом данные об используемых CSS селекторах накапливались чуть менее недели.