Рефакторинг CSS: Введение

Источник: «Refactoring CSS: Introduction (Part 1)»
Рефакторинг CSS — задача не из лёгких: его нужно провести так, чтобы не создать проблем. Сначала необходимо проанализировать существующую кодовую базу, провести аудит состояния CSS-кодовой базы, выявить слабые места, согласовать подход и убедить руководство в необходимости вложения времени и ресурсов в этот процесс.

CSS — это простой язык таблиц стилей для определения представления сайта или документа. Однако эта простота оставляет дверь открытой для многих потенциальных проблем и технических долгов — раздутый код, адская специфичность, дублирование блоков кода, не имеющих практически никаких различий, остатки неиспользуемых селекторов, ненужные хаки и обходные пути, и это лишь некоторые из них.

Такой технический долг, если он не выплачивается вовремя, может накапливаться и приводить к серьёзным проблемам в дальнейшем. Чаще всего это приводит к неожиданным побочным эффектам при добавлении новых компонентов пользовательского интерфейса и затрудняет сопровождение кодовой базы. Наверняка вам уже приходилось работать над проектом с плохой кодовой базой CSS и думать, как бы вы написали код по-другому, если бы была возможность провести рефакторинг или переписать все с нуля.

Рефакторинг больших частей CSS-кода — задача не из лёгких. Иногда может показаться, что это просто удаление некачественного кода, написание более качественного CSS и развёртывание блестящего улучшенного кода. Однако необходимо учитывать множество других факторов, таких как сложность рефакторинга живой кодовой базы, ожидаемая продолжительность и загруженность команды, постановка целей рефакторинга, отслеживание эффективности и прогресса рефакторинга и т.д. Кроме того, необходимо убедить руководство или заинтересованные стороны проекта в необходимости инвестировать время и ресурсы в процесс рефакторинга.

В этом цикле из трёх статей мы рассмотрим процесс рефакторинга CSS от начала и до конца: начнём со знаний о том, как к нему подходить, общих плюсов и минусов рефакторинга, затем перейдём к самим стратегиям рефакторинга и закончим общими рекомендациями по размеру CSS-файлов и производительности.

Побочные эффекты некачественного CSS

При всей своей гибкости и простоте сам CSS имеет ряд фундаментальных проблем, которые позволяют разработчикам писать некачественный код. Эти проблемы связаны с его спецификой и механизмами наследования, работой в глобальной области видимости, зависимостью от порядка источника и т.д.

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

В результате некачественный CSS может вызвать проблемы, выходящие за рамки простых визуальных ошибок, и привести к различным серьёзным побочным эффектам, которые могут повлиять на проект в целом. Среди таких примеров можно назвать следующие:

В худшем случае все вышеперечисленные проблемы в совокупности могут привести к большому размеру CSS-файла, даже с учётом минификации CSS. Такой CSS обычно блокирует рендеринг, поэтому браузер не будет отображать содержимое сайта, пока не закончит загрузку и разбор CSS-файла, что приведёт к ухудшению пользовательского интерфейса и производительности в медленных или ненадёжных сетях.

Эти проблемы затрагивают не только конечного пользователя, но и команду разработчиков и заинтересованных лиц проекта, делая сопровождение и разработку новых функций сложными, трудоёмкими и дорогостоящими. Это один из наиболее полезных аргументов, который можно привести при аргументации в пользу рефакторинга или перезаписи CSS.

Команда Netlify отметила, что причиной масштабного проекта по рефакторингу CSS стало снижение качества кода и его поддерживаемости по мере роста сложности проекта, в который добавлялось все больше и больше компонентов пользовательского интерфейса. Они также заметили, что отсутствие внутренних стандартов CSS и документации привело к снижению качества кода по мере того, как все большее количество людей работало над кодовой базой CSS.

(...) то, что начиналось с организованного PostCSS, постепенно превратилось в сложную и запутанную глобальную CSS-архитектуру с множеством особенностей и переопределений. Как и следовало ожидать, наступил момент, когда в связи с возникшим техническим долгом стало сложно продолжать быстрое обновление без регрессий. Кроме того, по мере роста числа фронтенд-разработчиков, вносящих свой вклад в кодовую базу, работать с такой CSS-архитектурой становится ещё сложнее.

Рефакторинг или переписывание

Рефакторинг позволяет разработчикам постепенно и стратегически улучшать существующую кодовую базу, не меняя её представления или основной функциональности. Эти улучшения, как правило, имеют небольшой объем и ограниченный характер, они не вносят разрушительных, масштабных архитектурных изменений и не добавляют в существующую кодовую базу новое поведение, возможности или функциональность.

Например, в текущей кодовой базе имеется два варианта компонента карточки — первый был реализован на ранних этапах разработки проекта опытным разработчиком, а второй был добавлен через некоторое время после запуска проекта менее опытным разработчиком в сжатые сроки, поэтому в нем присутствует дублированный код и селекторы с широким диапазоном, и высокой специфичностью.

Необходимо добавить третью вариацию карточки, которая использует некоторые стили двух других вариаций. Чтобы избежать ошибок, дублирования кода и сложных CSS-классов и HTML-разметки в будущем, команда решает провести рефакторинг CSS компонента карточки перед внедрением новой вариации.

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

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

Суммируем плюсы и минусы каждого подхода.

РефакторингПереписывание
Плюсы
  • Инкрементный и гибкий процесс
  • Работа с единой кодовой базой
  • Команда не зациклена на задачах рефакторинга
  • Легче убедить заинтересованные стороны и руководителей проекта в необходимости проведения рефакторинга
  • Возможность решения основных проблем: устаревший технологический стек, соглашения об именовании, архитектурные решения, внутренние правила и т.д.
  • Независимость от текущей кодовой базы (существующие возможности и слабые места...)
  • Долгосрочные планы по расширению и сопровождаемости кодовой базы
Минусы
  • Зависит от текущей кодовой базы и архитектуры ядра
  • Не позволяет решать основные проблемы
  • Архитектурные решения, существующие внутренние правила и лучшие практики, широкомасштабные проблемы и т.д.
  • Может быть сложным в исполнении, в зависимости от структуры проекта и состояния кодовой базы
  • Дорогостоящие и трудоёмкие
  • Необходимо полностью внедрить систему перед запуском
  • Поддержание текущей кодовой базы при разработке новой кодовой базы
  • Труднее убедить заинтересованные стороны и руководителей проекта в необходимости полной переделки

Когда следует проводить рефакторинг

Рефакторинг — это рекомендуемый подход для постепенного улучшения кодовой базы CSS при сохранении текущего внешнего вида (дизайна). Члены команды могут работать над решением этих проблем, когда нет более приоритетных задач. Постепенное улучшение текущей кодовой базы в большинстве случаев не скажется непосредственно на пользовательском опыте, однако более чистая и удобная в обслуживании кодовая база приведёт к упрощению реализации функций и уменьшению количества неожиданных ошибок и побочных эффектов.

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

Рефакторинг CSS следует проводить регулярно, если в ближайшее время не планируется масштабных изменений дизайна или содержания. Команды должны активно искать ранее упомянутые слабые места в текущей кодовой базе CSS и работать над их устранением при отсутствии более приоритетных задач.

Ведущий фронтенд-разработчик или разработчик с наибольшим опытом работы с CSS должен поднимать проблемы и создавать задачи рефакторинга, чтобы обеспечить соблюдение стандартов качества CSS-кода в кодовой базе.

Когда следует переписывать код

Переписывать всю кодовую базу CSS следует в тех случаях, когда в кодовой базе CSS есть основные проблемы, которые не могут быть решены с помощью рефакторинга, или когда рефакторинг является более дорогостоящим вариантом. Исходя из личного опыта, когда я начинал работать с клиентами, перешедшими из другой компании и имевшими вышеупомянутые проблемы с CSS, и было очевидно, что рефакторинг будет сложной задачей, я начинал с рекомендации полного переписывания и смотрел, что думает клиент. В большинстве случаев такие клиенты были недовольны состоянием кодовой базы и с удовольствием приступали к переписыванию.

Ещё одна причина для полной переделки CSS — когда планируется существенное изменение сайта — ребрендинг, редизайн или любое другое значительное изменение, затрагивающее большую часть сайта. Можно предположить, что участники проекта понимают, что речь идёт о значительных инвестициях, и на завершение переписывания потребуется некоторое время.

Аудит состояния кодовой базы CSS

Когда команда разработчиков пришла к выводу, что CSS-код нуждается в рефакторинге для оптимизации рабочего процесса разработки функций или устранения неожиданных побочных эффектов и ошибок CSS, ей необходимо донести это предложение до заинтересованных сторон проекта или руководителя проекта.

В дополнение к субъективным мыслям о кодовой базе и общему обзору кода неплохо было бы предоставить некоторые конкретные данные. Это также даст команде измеримые цели, которые они могут знать в процессе работы над рефакторингом — целевой размер файла, специфичность селекторов, сложность CSS-кода, количество медиа-запросов…

При проведении CSS-аудита или подготовке к CSS-рефакторингу я использую несколько полезных инструментов для получения общего обзора и полезных статистических данных о кодовой базе CSS.

Мой личный инструмент — CSS Stats, бесплатный инструмент, предоставляющий полезный обзор качества кодовой базы CSS с множеством полезных показателей, которые могут помочь разработчикам выявить некоторые трудноуловимые проблемы.

Ещё в 2016 году компания trivago провела масштабный рефакторинг своей CSS-кодовой базы и, используя метрики CSS Stats, поставила перед собой конкретные, измеримые цели, такие как снижение специфичности и уменьшение количества цветовых вариаций. Всего за три недели им удалось улучшить общее состояние кодовой базы CSS, уменьшить размер CSS-файлов, повысить производительность рендеринга на мобильных устройствах и т.д.

Такой инструмент, как CSS Stats, может легко помочь вам выявить проблемы согласованности в вашей кодовой базе. Показывая, что может произойти, когда у всех разные мнения о том, как должен выглядеть серый тон, вы в итоге получите 50 оттенков серого. Более того, Specificity Graph даёт хорошее общее представление о состоянии вашей CSS-базы.

Что касается инструментов CLI, то Wallace — это удобный инструмент, предоставляющий несколько базовую, но полезную статистику и обзор CSS, который можно использовать для выявления проблем, связанных с размером файла, количеством правил и селекторов, типами и сложностью селекторов и т.д.

Wallace также предлагает бесплатный инструмент анализатора на сайте Project Wallace, который использует, по-видимому, более продвинутую версию Wallace в бэкенде, чтобы обеспечить некоторые полезные визуализации данных и несколько дополнительных метрик, недоступных в Wallace CLI.

Project Wallace также предлагает полноценное платное решение для аналитики кодовой базы CSS. В нем реализовано ещё больше полезных функций и метрик, которые помогут разработчикам выявить некоторые трудноуловимые проблемы и отслеживать изменения CSS-статистики на основе каждого коммита. Хотя платный тарифный план включает больше функций, бесплатного тарифного плана и базового инструмента CSS-анализатора более чем достаточно для аудита качества кодовой базы CSS и получения общей картины для составления планов рефакторинга.

Написание высококачественного CSS

Мы видели, как простота и гибкость кодовой базы CSS может вызвать множество проблем с качеством кода, производительностью и визуальными ошибками. Не существует автоматического инструмента, который бы гарантировал, что мы пишем CSS наилучшим образом и избегаем всех возможных архитектурных ловушек на этом пути.

Лучшими инструментами, обеспечивающими написание качественного CSS-кода, являются дисциплина, внимание к деталям, а также общие знания и навыки работы с CSS. Разработчику необходимо постоянно осознавать общую картину и понимать, какую роль играет его CSS в этой общей картине.

Например, слишком сильная специфичность селекторов может сильно ограничить удобство использования, в результате чего другим разработчикам придётся дублировать код, чтобы использовать его для других, похожих компонентов с другой разметкой. Такие проблемы часто возникают, когда разработчики не понимают и не используют механизмы, лежащие в основе CSS (каскад, наследование, производительность браузера и специфичность селекторов). Такие ранние решения могут привести к серьёзным последствиям в будущем, поэтому здоровье и работоспособность кодовой базы CSS зависят от знаний, навыков и понимания разработчиком основ CSS.

Автоматизированные инструменты не знают общей картины и того, как используется селектор, поэтому они не могут принимать такие важные архитектурные решения, кроме как навязывать некоторые основные, предсказуемые и жёсткие правила.

Основываясь на личном опыте, я убедился в том, что нижеперечисленное помогло мне значительно улучшить работу с CSS:

Также важно установить правила и внутренние стандарты CSS внутри команды или даже для всей компании. Чётко сформулированные общекорпоративные стандарты, стиль кода и принципы могут дать множество преимуществ, таких как:

Kirby Yardley работал над рефакторингом системы дизайна и CSS Института Sundance и отметил важность создания внутренних правил и лучших практик.

Без надлежащих правил и стратегии CSS — это язык, который может быть использован не по назначению. Часто разработчики пишут стили, характерные для одного компонента, не задумываясь о том, как этот код можно повторно использовать в других элементах (...) После долгих исследований и размышлений о том, как мы хотим подойти к созданию архитектуры CSS, мы решили использовать методологию под названием ITCSS.

Возвращаясь к предыдущему примеру команды trivago, следует отметить, что важным шагом в процессе рефакторинга оказалось установление внутренних правил и рекомендаций.

Мы внедрили библиотеку паттернов, начали использовать атомарный дизайн в нашем рабочем процессе, создали новые рекомендации по кодированию и адаптировали несколько методологий, таких как БЭМ и ITCSS, чтобы поддерживать и развивать наши CSS/UI в больших масштабах.

Не все правила и стандарты необходимо проверять и применять вручную. Такие инструменты CSS linting, как Stylelint, предоставляют ряд полезных правил, которые помогут проверить наличие ошибок и обеспечить соблюдение внутренних стандартов и общих правил CSS, таких, как запрет пустых блоков кода CSS и комментариев, запрет дублирования селекторов, ограничение единиц измерения, установка максимальной специфичности и глубины вложенности селекторов, определение шаблона имени селектора и т.д.

Заключение

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

Такие полезные инструменты, как CSS Stats и Wallace, позволяют получить общий высокоуровневый обзор кодовой базы CSS и детальное представление о состоянии и здоровье кодовой базы. Эти инструменты также предоставляют измеримые статистические данные, которые можно использовать для постановки целей процесса рефакторинга и отслеживания его хода.

После определения целей и масштабов рефакторинга важно установить внутренние рекомендации и лучшие практики для кодовой базы CSS — соглашение об именовании, архитектурные принципы, структура файлов и папок и т.д. Это обеспечит согласованность кода, создаст основу проекта, которую можно документировать и использовать при внедрении и проверке CSS-кода. Использование таких инструментов линтинга, как Stylelint, может помочь внедрить некоторые общие лучшие практики CSS и частично автоматизировать процесс проверки кода.

В следующей статье из этого цикла мы рассмотрим стратегию рефакторинга CSS, которая обеспечивает плавный переход между текущей кодовой базой и рефакторингом.

Дополнительные материалы

Предыдущая Статья

Шесть возможностей JavaScript ES12, которые следует использовать

Следующая Статья

Laravel: Добавление или изменение данных Request перед валидацией