Обзор на новую CSS-in-JS либу от Facebook* – StyleX

от автора

Недавно компания Facebook* (aka Meta**) выпустила в опенсорс собственную CSS-in-JS библиотеку под названием StyleX. По заявлениям разработчиков, она отлично подходит для больших проектов и ключевым ее преимуществом является перфоманс.

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


Начать стоит с того, что StyleXframework agnostic. Это означает, что библиотеку можно использовать с любым JS фреймворком, будь то React, Preact, Solid, Angular или Qwik. Однако те, что используют кастомные расширения файлов, типа Svelte и Vue, могут потребовать дополнительной настройки.

Предлагаю взглянуть на компонент Button, написанный на React и TypeScript:

import * as React from "react"; import * as stylex from "@stylexjs/stylex"; import type { StyleXStyles } from "@stylexjs/stylex/lib/StyleXTypes";  const MEDIA_MOBILE = "@media (max-width: 700px)" as const;  const ButtonStyles = stylex.create({   base: {     border: "none",     background: "none",     cursor: "pointer",     // Использование медиа-запросов     fontSize: {       default: "24px",       [MEDIA_MOBILE]: "16px",     },   },   primary: {     color: "white",     backgroundColor: "black",   },   secondary: {     color: "black",     backgroundColor: "white",   },   block: {     display: "flex",     width: "100%",   },   dynamic: (opacity) => ({     opacity,   }), });  const Button = ({   color = "primary",   block = false,   styles, }: {   color: string;   block: boolean;   styles?: StyleXStyles<{     backgroundColor?: string;     color?: string;   }>; }) => {   return (     <button       {...stylex.props(         // Применяется по умолчанию         ButtonStyles.base,         // Применяется один из вариантов в зависимости от пропса color         ButtonStyles[color],         // Применяется условно в зависимости от пропса block         block && ButtonStyles.block,         // Применяется результат выполнения функции dynamic         ButtonStyles.dynamic(state.opacity),         // Стили, прокинутые пропсом         styles       )}     />   ); }; 

Библиотека имеет довольно простое API, мы разберем основные функции и типы. С остальными можно ознакомиться по ссылке.

С помощью stylex.create() создается объект стилей, свойства которого мы можем передать в stylex.props() условно, по ключу или динамически – с использованием функции. Так как props() возвращает объект, его нужно развернуть через spread-оператор.

А используя встроенный тип StyleXStyles мы можем ограничить css-свойства, передаваемые извне.

В StyleX также доступно создание переменных, на которых можно строить дизайн-систему:

import * as stylex from '@stylexjs/stylex';  const colors = stylex.defineVars({   accent: 'blue',   background: 'white', });

Обращение к ним происходит так же, как и к обычным свойствам объекта:

import * as stylex from '@stylexjs/stylex'; import {colors} from './vars.stylex.js';  const styles = stylex.create({   container: {     color: colors.accent,     backgroundColor: colors.background,   }, });

Ключевые преимущества

Разработчики библиотеки декларируют ряд достоинств:

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

  • Масштабируемость – гениальный Babel-плагин использует кэширование на уровне файлов и генерирует атомарные названия классов, за счет чего минимизируется размер бандла, а рост количества компонентов в приложении не сильно отражается на размере CSS файла.

  • Предсказуемость – приоритизация селекторов в StyleX очень проста – всегда побеждает последний заданный стиль. Это значит, что можно забыть про каскадность.

  • Комбинируемость – объекты стилей можно экспортировать и передавать в компоненты. При этом стили всегда будут вести себя предсказуемо.

  • Типизация – каждое css-свойство и переменная полностью типизированы, а мы можем использовать TypeScript или Flow, чтобы определить стили, передаваемые в компонент.

  • Все в одном месте – библиотека поощряет определение стилей в том же файле, что и компонента. При таком подходе StyleX удаляет неиспользуемые свойства из бандла и убирает дубликаты.

История создания

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

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

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

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

В результате перехода на StyleX размер первоначального CSS бандла facebook.com составил 140 Кбайт. На первый взгляд может показаться, что это много, но нужно учитывать, что эти стили покрывают 100% приложения. Браузер загружает их всего один раз, а потом достает кэша.

Конкуренты

По-моему, сравнивать StyleX, в первую очередь, стоит с Emotion и Tailwind.

Тут у нас, как и в Emotion, co-located подход – стили находятся в одном файле с компонентом. Для многих это большой плюс с точки зрения DX и читабельности кода. Но в то же время, StyleX обгоняет конкурента за счет отсутствия рантайм-нагрузки.

В сравнении с Tailwind, библиотека не так проста и удобна – мы не можем использовать сокращения из коробки, их придется создавать самостоятельно.

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

Заключение

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

Компания Facebook* три года тестировала и дорабатывала свой продукт, прежде чем отдать его в опенсорс. Мне кажется, это достаточное основание полагать, что библиотека проверена и может использоваться в реальных проектах.

Лично я рад появлению этой технологии, а что думаете вы?

*Социальная сеть запрещена в России

**Компания Meta Platforms Inc. признана в России экстремистской организацией и запрещена.


ссылка на оригинал статьи https://habr.com/ru/articles/781166/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *