Как стать автором
Обновить

Почему вам стоит использовать Styled Components

Время на прочтение7 мин
Количество просмотров17K

Привет Хабр! Недавно мне попался на рефакторинг один сайт написанный одним студентом. Он был реализован не лучшим образом и уже давно следовало бы его исправить. И вот наконец у меня выдалось свободное время на рефакторинг. Сайт был написан на Next.js, для написания стилей использовались SCSS Modules. А так как я на своих проектах уже давно использую Styled Components тут же в глаза бросился дискомфорт от использования обычного SCSS. И в этой статье я вам расскажу что же это за дискомфорт и как же Styled Components позволяет от него избавиться.

Сразу сделаю уточнение. Под Styled Components я имею ввиду не только библиотеку styled-components, а любую другую выполненную в концепции CSS-in-JS, например emotion, glamorous, styletron и подобные. Я же использую именно библиотеку styled-components потому что она имеет самое большое сообщество, отличную документацию, а в next.js уже встроена его поддержка.

А теперь о конкретных преимуществах.

Легко писать сложные компоненты

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

Цветов может быть 4 варианта, стили 3 варианта, формы кнопки 3 варианта, размеры кнопки 3. В итоге кнопка может иметь 108 состояний. Как написать стили SCSS для такой кнопки? Скорее всего вы воспользуетесь методологией БЭМ напишите стили компонента и его модификаторы. И будет это выглядеть следующим образом:

.button {
    padding: 0.5rem 1rem;
    ...other styles...

    &[color="primary"] {
        color: #1976d2;
        background-color: #ffffff;
    }

    &...other colors... {}

    $[variant="contained"] {
        color: #ffffff;
        background-color: #1976d2;
    }
  
    &...other variants... {}

    $[disabled] {
        color: #b6b6b6;
        background-color: #e0e0e0;
    }
}

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

.button {
    padding: 0.5rem 1rem;
    ...other styles...

    $[variant="contained"] {
        color: #ffffff;
        background-color: #1976d2;
      
        $[disabled] {
            color: #b6b6b6;
            background-color: #e0e0e0;
      }
    }

    ...other styles...
}

Как же эту проблему решает Styled Components? А все просто. Вы пишите логику ровно так как вы привыкли это делать в Typescript.

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

interface IStyledButtonProps {
    color?: ButtonColors;
    variant?: ButtonVariants;
    disabled?: boolean;
}

export const StyledButton = styled.button<IStyledButtonProps>((props) => {

    // Set colors
    let primaryColor = "#1976d2";
    let secondaryColor = "#1976d2";

    if (props.color === ButtonColors.Secondary) {
        primaryColor = "other colors";
        secondaryColor = "other colors";
    } ...other colors...

    
    // Set styles
    let textColor = primaryColor;
    let bgColor = secondaryColor;

    if (props.variant === ButtonVariants.Contained) {
        textColor = secondaryColor;
        bgColor = primaryColor;
    } ...other variants...


    // Result CSS
    return css`
        color: ${textColor};
        background-color: ${bgColor};
        ...other styles...
    `;
});

Таким образом используя вместо бедного языка CSS мощный язык TypeScript вы на порядок упрощается сложность написания стилей. И вместо огромного каскада сложных перевложенных стилей получается простой и лаконичный код компонента.

Кроме того стили написанные на Styled Components, по моей практике, в среднем весят в 2-3 раза меньше чем стили написанные на SCSS. Что положительно влияет на размер бандла и скорость работы сайта.

Стили типизированы

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

И теперь у вас не просто мощный инструмент для написания стилей, но и автокомплит и статический анализатор который не позволит совершить ошибку в модификаторе. А так же сообщит об ошибке в случае изменения в API компонента.

Переход к стилям по горячей клавише

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

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

Мертвые стили не попадают в сборку

У CSS есть большая проблема, все что попало в CSS остается в нем навсегда. Никто никогда не занимается чисткой CSS стилей. А по мере роста приложения и количества рефакторингов эта проблема начинает влиять на скорость сайта.

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

Теперь сайт не подвержен проблеме уменьшения скорости работы из-за роста баласта мертвых стилей, ведь теперь в сборке только актуальные стили.

Нету не используемых модификаторов стилей

В первом примере мы рассматривали кнопку. Когда мы пишем модификаторы для кнопки на SCSS то все написанные модификаторы попадают в сборку. Это плохо сказывается на скорости сайта, в т.ч. на SSR и скорость рендеринга стилей. Мы написали 108 состояний кнопки, но на странице используется только 1 состояние.

Styled Component работает по другому. Он в рантайме высчитывает стили и использует только те стили которые используются в данный момент. Таким образом если используется только одно состояние у кнопки то и в стили SSR попадет только одно состояние, а значит и у клиента страница прогрузится и отрисуется быстрее.

Можно использовать динамические стили

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

Для примера. Я использую сеточный фреймворк. Все сеточные фреймворки имеют преднастройку на 12 колонок. А что делать если мне понадобилось 8 колонок? Пересобирать второй сеточный фреймворк для проекта?

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

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

Предотвращение конфликтов стилей

Styled Components не использует имен селекторов, вместо этого он использует хэшь от стиля. Примерно так же как это делает SCS Modules. Таким образом вам не надо бояться того что селекторы стилей начнут конфликтовать друг с другом.

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

Позволяет использовать вложенные стили

Бывают ситуации когда внутри вашего компонента рисуется компонент из внешней библиотеки. Например внутри вашего блока рисуется слайдер от библиотеки Swiper. И вам необходимо поправить несколько стилей от этой библиотеки. Например перекрасить стрелочки из синих в красные.

В SCSS Modules вы столкнётесь с проблемой при такой задаче, поскольку он не позволяет писать вложенные стили.

В Styled Components вы без проблем можете написать вложенный стиль и стилизовать внешнюю библиотеку в нужном месте.

Производительность

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

Источник: https://github.com/geeky-biz/css-in-js-benchmark
Источник: https://github.com/geeky-biz/css-in-js-benchmark

В чем проблема данного теста? Он тестирует только идеальный случай. Когда у вас есть только свежие стили и никакого мусора. В реальных же приложениях количества мусора в CSS быстро растет и начинает потреблять слишком много ресурсов. Styled Components же, как писал выше, вырезает мертвые стили из сборки. Поэтому с ростом приложения Styled Components будет все больше и больше выигрывать в плане перформанса.

Styled Components действительно дольше инициализируется за счет того что он работает в рантайме. Только у меня разница составляла не 40%, а всего 10%. Styled Components действительно быстрее рендерит изменения на страницах, за счет того что в движке браузера CSS гораздо меньше стилей и эти стили гораздо проще организованы для движка.

В сравнению с Linaria в Styled Components можно работать с динамическими компонентами и не зависеть от системы сборки.

CSS Modules может конкурировать со Styled Components только в плане инкапсуляции селекторов. При этом он не решает проблем написания сложных компонентов, удаления мертвых стилей и остальные проблемы.

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

Идеально для Микрофронтендов

Styled Components имеет очень маленький размер библиотеки, всего 35кб минифицированного кода. За счет чего он является отличным кандидатом для встраивания в микрофронтенд.

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

Вывод

Styled Components это не альтернатива CSS, Less, SCSS, CSS Modules. Это технология позволяющая писать CSS на совершенно новом уровне.

Переход с SCSS на Styled Components по своей эффективности можно сравнивать с переходом с html на jsx.

Считаете слишком приукрасил Styled Components? Готов поспорить в комментариях!

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 17: ↑4 и ↓13-9
Комментарии37

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн