Привет, WSD!
Что имеем?
беспорядочный проект
хаотичный редизайн
нет организации CSS кода
слабая структурированность
Что мы хотим?
быструю загрузку
быструю отрисовку
красивый код
модульность
постоянный рефакторинг
Что для этого нужно?
переделать все
уменьшить размер CSS
оптимизировать загрузку ресурсов
разделить CSS на логические части
много трудиться
Инструменты и практики
UnCSS
анализирует статические файлы или URL
JSDOM
для эмуляции работы браузера
PostCSS
для парсинга CSS
npm install uncss
UnCSS
const uncss = require('uncss');
const files = ['index.html', 'https://google.com'];
uncss (files, function (error, clearCSS) {
console.log(clearCSS);
});
UnCSS | Преимущества
можно использовать в системах сборки: gulp, grunt, broccoli
есть online версия https://uncss-online.com/
умеет анализировать CSS
, добавленный на JS
использует JSDOM
, не требует запуска браузера
отлично подходит для статических сайтов
UnCSS | Недостатки
проводит анализ стилей только по событию "onload
"
не умеет обрабатывать изменения DOM
не умеет обрабатывать закрытые разделы
отлично подходит для статических сайтов
uCSS
анализирует статические файлы или URL
Cheerio
для работы с DOM
CSSOM
для парсинга CSS
npm install ucss
uCSS | Выводы
преимущества и недостатки как у UnCSS
не нашел интеграции с системами сборки
не поддерживается, не было коммитов 2 года
нет online версии
Helium CSS
<script src="helium.js "></script>
<script type="text/javascript">
window.addEventListener('load ', function(){
helium.init();
}, false);
</script>
Helium CSS | Выводы
исполняется в браузере
сложно встроить в линию сборки
предоставляет информацию, но не понятно что с ней делать
не поддерживается, не было коммитов 4 года
Finding Dead CSS
Как мы узнаем о том, что CSS код мертв?
Несмотря на то, что инструменты вроде uncss очень мощные, они не совсем подходят под наши требования.
А что, если нам нужно решение в основу которого положен принцип мониторинга реальных пользователей,
который позволяет увидеть какой код действительно используется у реальных пользователей на реальном сайте?
Harry Roberts, ссылка на статью →
Finding Dead CSS | Реализация
.some .selector {
background-image: url('/img/dead/some_selector.gif');
color: red;
padding: 0;
}
Finding Dead CSS | Идея
помечаем селекторы
включаем access логи сервера
накапливаем информацию
все что попало в access логи – живо
Finding Dead CSS | Анализ
дополнительные ресурсы у страницы
нужно вручную пометить весь CSS код
сложно анализировать access логи
GIF можно не создавать и сделать rewrite на сервере
пользователи сами накапливают статистику
Требования
анализ существующего CSS
автономный сбор и хранение данных
анализ динамического контента:
модальные окна
отложенно загружаемый контент
повторное использование с тем же результатом
Идея
собрать существующие селекторы
протестировать на актуальность силами посетителей
накопить результат
очистить CSS
Инструменты
парсер AST для CSS
временное хранилище данных на клиенте
постоянное хранилище данных на сервере
Требования к парсеру в AST
нет требований к производительности
должен обрабатывать комментарии
простой и с хорошей документацией
С чем работаем?
Rule | Правило
.title-search-item :hover {
prop: value;
...
}
At-rule | Директива
@media screen and (max-width: 1200px) {
...
}
Работаем с правилами и селекторами
.title-search-item { ... }
.title-search-item a:hover { ... }
.title-search-item :hover { ... }
.cart-amount__title::after { ... }
Отбрасываем псевдоклассы и псевдоэлементы /(>?\s?:[\S]+)/g
Парсер в AST
Rework CSS parser
CSSTree
PostCSS
Rework CSS parser
const parser = require('css')
...
var { stylesheet: { rules } } = parser.parse(cssString)
walker (rules, (filtered) => {
...
}, walker);
Rework CSS parser
работает
комментарии входят в AST как отдельный тип правил
нет собственного метода обхода дерева
коммит 4 года назад
Rework устарел
CSSTree
const csstree = require('css-tree');
...
var ast = csstree.parse(cssString);
csstree.walk (ast, function(node) {
...
});
CSSTree
быстрый
современный
отличная документация и API
отбрасываются комментарии
отбрасываются пробелы, теряется форматирование
PostCSS
const postcss = require('postcss');
const proc = postcss((ast) => {
ast.walkRules (/^\D/, (rule) => {
let { selector } = rule;
...
});
}).process(cssString).then(result => {...});
PostCSS
быстрый
современный
отличная документация и API
можно сохранить форматирование
Получаем список селекторов
ast.walkRules(/^\D/, (rule) => {
let { selector } = rule;
selector = selector.replace(/\n/g, '');
selectors .push(...selector.split(','));
});
Получаем список селекторов
[
".rightcol-profile .button-cancel",
".cart-step-3 .prb span",
"#block-analogues-popup .prb span",
".cart-step-3 .prb.old::after ",
...
]
Что-то забыли?
модальные окна
состояния UI компонентов
рендер компонентов на стороне клиента
Событие
использовали DOM EventListener
добавили генерацию события для случаев изменения DOM
модифицировали JS код проекта
Свой сервер с БД
он обычно есть
легко интегрировать (например, POST запрос с клиента)
дополнительная нагрузка на сервер
Google Firebase
есть бесплатный аккаунт, не требует дополнительных расходов
не нагружается основная база и сервер
относительная легкость в интеграции
тяжеловесная клиентская библиотека (~ 100KB, gzip)
Результат в JSON
{
"url" : "/index.html",
"data" : [
".rightcol-profile .button-cancel",
".cart-step-3 .prb span",
".selector1", ".selector2", ".selector3"
...
]
}
Схема работы
На сервере
создаем индекс CSS селекторов
cssclear index ./css path/to/selectors.json
...
очищаем CSS файлы
cssclear clear -f path/to/live.json ./css ./dest
На клиенте
<script>
var cssClear = {
pathToSelectors: 'https://yourdomain.com/selectors.json',
dataStoreProvider: {
name: 'postData',
options: {
apiKey: "d58e3582afa99040e27b92b13c8f2280",
URL: 'https://apidomain.com/save/point/'
}
}
};
</script>
<script async src="path/to/csscleaner.bundle.js"></script>
Подготовка
тестирование
E2E тесты
тесты CSS регрессий
мониторинг метрик загрузки сайта
Результат
сократили CSS код в 3 раза
365кб не сжатого CSS против ~1200кб
получили небольшой прирост в Google Insights
получили инструмент для повторного использования
получили удовольствие
ссылка на GitHub