Linaria может быть лучшим JSS-решением для React прямо сейчас

React.js

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

представлять

Линария — этонулевое время выполненияФреймворк JSS, его особенности:

  • Внедрить CSS в систему JS, и эта поддержка предоставляется бесплатно! Код, связанный с CSS, будет извлечен в файл CSS во время компиляции.
  • Sass-подобный синтаксис CSS
  • Linaria поддерживает быстрое создание компонентов в стиле React с динамическими свойствами с помощью переменных CSS.
  • Использование исходных карт CSSЛегко найти местоположение стиля
  • поддержка стилета
  • Препроцессор больше не нужен, вы можетеИспользуйте логику для управления CSS JavaScript
  • ноПоддерживает использование препроцессоров, такие как Sass или PostCSS

Преимущества перед традиционными решениями CSS

1. Стилевая изоляция

const title = css`
  font-size: 18px;
`;

Подобный код в конечном итоге будет скомпилирован в

.k4yi6fg {
  font-size: 18px;
}

Его имя класса определяется путем вычисления хеш-значения пути к файлу.

2. Стили и компоненты принадлежат одному и тому же файлу

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

3. Надежная и безопасная поддержка рефакторинга

Поскольку стили JSS на самом деле являются просто переменными JS, вы можете легко найти логику стиля, связанную с компонентом, через логику кода, не опасаясь, что рефакторинг вызовет неожиданные эффекты.

4. Препроцессор больше не нужен

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

Например, вы можете написать такой код


const DEFAULT_COLOR = '#fffff'
const PRIMARY_COLOR = '#de2d68';

const getColor = Math.random() > 0.5 ? PRIMARY_COLOR : DEFAULT_COLOR;

const button = css`
  background-color: ${getColor()};

  &:hover {
    background-color: ${Math.random() > 0.5 ? PRIMARY_COLOR : DEFAULT_COLOR};
  }
`;

5. Tree shaking

Как мы только что сказали, JSS на самом деле просто переменная JS, поэтому, естественно, то, что JS может делать встряхивание дерева, Linaria может делать то же самое. Это на самом деле очень привлекательно для разработчиков UI-библиотек: больше не нужно вводить дополнительные плагины babel, а автоматически вводятся стили по запросу через встряхивание дерева.

6. Автоматически добавлять префиксы браузера

Linaria автоматически добавит префиксы браузера, чтобы помочь вам поддерживать некоторые специальные свойства для совместимости, и вы по-прежнему можете использовать PostCSS для дальнейшей оптимизации.

7. Возможность декларативно и динамически стилизовать компоненты React.

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

const Box = styled.div`
  background-color: orange;
  height: ${props => props.size}px;
  width: ${props => props.size}px;
`;

<Box size={48}>

Преимущества перед препроцессорами CSS

1. Никаких новых затрат на обучение

Синтаксис Linaria можно рассматривать как просто поддерживающий вложенный синтаксис CSS. Никаких переменных, примесей или функций, их можно заменить логикой JS.

2. Преимущества перед традиционными схемами CSS одинаковы для препроцессоров CSS.

Преимущества перед написанием встроенных стилей напрямую

1. Полная поддержка возможностей CSS

Встроенные стили имеют ограничения, а Linaria поддерживает все возможности CSS:

  • запросы средств массовой информации
  • CSS3 анимация
  • псевдокласс, псевдоэлемент

2. Преимущества производительности

Применение стилей с помощью именования классов выполняется быстрее, чем встроенные стили.

Преимущества перед другими решениями JSS

1. CSS загружается и парсится отдельно от JS

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

2. Никаких дополнительных затрат на парсинг

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

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

3. Нет потери производительности за повторный рендеринг во время SSR.

Для JSS-фреймворков, основанных на компонентах, рендеринг одного и того же компонента с разными реквизитами приведет к тому, что один и тот же стиль будет копироваться несколько раз, что увеличивает размер продукта во время SSR. Хотя в большинстве случаев о снижении производительности из-за этой проблемы не стоит упоминать, при отображении множества больших списков с небольшими различиями размер легко увеличивается.

Кроме того, при выполнении SSR нужно извлекать CSS-стиль, записанный в JS-файле, а затем передавать его в браузер, что также увеличивает объем продукта.

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

4. Проверка времени компиляции на наличие синтаксических ошибок

Недопустимые значения JS и неправильный синтаксис CSS проверяются во время компиляции, а не обнаруживаются во время выполнения. Это означает, что вы не столкнетесь с этими низкоуровневыми ошибками в производственном режиме, а также, Linaria поддерживает stylelint, и вы все еще можете получить тот же опыт работы с lint, что и раньше.

5. Знакомый синтаксис CSS

В отличие от некоторых других фреймворков JSS, синтаксис Linaria поддерживает только вложенный нативный синтаксис CSS, и для начала работы не требуется никаких затрат. Идеальная поддержка программирования Copy-Paste

6. Поддерживает работу без JavaScript

Если ваш веб-сайт должен работать с отключенным JavaScript или если вы хотите скомпилировать статические страницы, Linaria также может работать в этих ситуациях, потому что еенет времени выполненияхарактеристика

Конфигурация установки

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

первый

Если вы используете Babel для транспиляции или полифилла в своем проекте, вы должны создать конфигурационный файл Babel под корневым проектом, и прописать в нем нужные пресеты и плагины, иначе Linaria не сможет разобрать ваш код

Работа с вебпаком

С Webpack легко работать, просто добавьте babel-loaderlinaria/loaderДа, убедитесьlinaria/loaderрядом с и после babel-loader

{
  test: /\.js$/,
  use: [
    { loader: 'babel-loader' },
    {
      loader: 'linaria/loader',
      options: {
        sourceMap: process.env.NODE_ENV !== 'production',
      },
    }
  ],
}

Также для извлечения собранных стилей нужен еще один плагин Webpackmini-css-extract-plugin, воплощать в жизньnpm i -D css-loader mini-css-extract-pluginустановить

затем импортироватьmini-css-extract-plugin

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

Затем установите соответствующие правила парсинга и плагины

{
  test: /\.css$/,
  use: [
    {
      loader: MiniCssExtractPlugin.loader,
      options: {
        hmr: process.env.NODE_ENV !== 'production',
      },
    },
    {
      loader: 'css-loader',
      options: {
        sourceMap: process.env.NODE_ENV !== 'production',
      },
    },
  ],
},

Пучокmini-css-extract-pluginДобавлено в конфиг Webpackpluginsатрибут

new MiniCssExtractPlugin({
  filename: 'styles.css',
});

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

new MiniCssExtractPlugin({
  filename: 'styles-[contenthash].css',
});

Потому что Linaria будет проходить через Webpack с извлеченными файлами стилей..cssОбычный конвейер загрузчика, так что вы можете легко использоватьpostcssилиclean-cssсделать некоторые настройки

Полный пример конфигурации Webpack

const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const dev = process.env.NODE_ENV !== 'production';

module.exports = {
  mode: dev ? 'development' : 'production',
  devtool: 'source-map',
  entry: {
    app: './src/index',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: '[name].bundle.js',
  },
  optimization: {
    noEmitOnErrors: true,
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV) },
    }),
    new MiniCssExtractPlugin({ filename: 'styles.css' }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          { loader: 'babel-loader' },
          {
            loader: 'linaria/loader',
            options: { sourceMap: dev },
          },
        ],
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              hmr: process.env.NODE_ENV !== 'production',
            },
          },
          {
            loader: 'css-loader',
            options: { sourceMap: dev },
          },
        ],
      },
      {
        test: /\.(jpg|png|gif|woff|woff2|eot|ttf|svg)$/,
        use: [{ loader: 'file-loader' }],
      },
    ],
  },
  devServer: {
    contentBase: [path.join(__dirname, 'public')],
    historyApiFallback: true,
  },
};

Вы можете установить все необходимые библиотеки npm с помощью следующей команды

npm i -D webpack webpack-cli webpack-dev-server mini-css-extract-plugin css-loader file-loader babel-loader

Настройте свойство options linaria/loader

Вы можете передать свойство options, подобное этому

{
  loader: 'linaria/loader',
  options: {
    sourceMap: false, // 是否产生 CSS source map,默认 false
    cacheDirectory: '.linaria-cache', // 缓存所在文件见,默认 .linaria-cache
		extension: '.linaria.css', // CSS 文件处于中间态时的命名,默认 .linaria.css
		preprocessor: 'stylis', // 定义 css 的预处理器,默认为 stylis

  },
}

Как использовать

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

API браузера

css```

cssЯвляетсяфункция метки, что означает, что вы можете передать строку шаблона ```` вместо()для вызова этой функции результат оценки функции метки будет преобразован плагином Babel в уникальное имя класса.

import { css } from 'linaria';

const flower = css`
  display: inline;
  color: violet;
`;

// flower === flower__9o5awv –> with babel plugin

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

import { css } from 'linaria';

const box = css`
  animation: rotate 1s linear infinite;

  @keyframes rotate {
    { from: 0deg; }
    { to: 360deg; }
  }
`;

cx(...classNames: Array<string | false | void | null | 0>) => string

cx()Объединяет входящую строку, но игнорирует ееFalsyзначение, например'',nullа такжеundefinedЖдать

import { css, cx } from 'linaria';

const cat = css`
  font-weight: bold;
`;

const yarn = css`
  color: violet;
`;

const fun = css`
  display: flex;
`;

function App({ isPlaying }) {
  return <Playground className={cx(cat, yarn, isPlaying && fun)} />;
}

cx()Эта функция очень похожа на популярную библиотекуclassnames, но отличия все же естьcx()Объект не обработан

styled

Вспомогательный объект для быстрого создания компонентов React, он используется какstyled-components:

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

import { styled } from 'linaria/react';
import colors from './colors.json';

const Container = styled.div`
  background-color: ${colors.background};
  color: ${props => props.color};
  width: ${100 / 3}%;
  border: 1px solid red;

  &:hover {
    border-color: blue;
  }
`; 

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

const Title = styled.h1`
  font-size: 36px;
`;

const Article = styled.article`
  font-size: 16px;

  /* this will evaluate to the selector that refers to `Title` */
  ${Title} {
    margin-bottom: 24px;
  }
`;

И мы можем пройтиasатрибут, чтобы указать, что на самом деле отображает HTML-тег

// Here `Button` is defined as a `button` tag
const Button = styled.button`
  background-color: rebeccapurple;
`;

// You can switch it to use an `a` tag with the `as` prop
<Button as="a" href="/get-started">
  Click me
</Button>;

styledТакже поддерживает вложение стилей в виде компонентов более высокого порядка.

const Button = styled.button`
  background-color: rebeccapurple;
`;

// The background-color in FancyButton will take precedence
const FancyButton = styled(Button)`
  background-color: black;
`;

API сервера (linaria/server)

collect(html: string, css: string) => string

При выполнении SSR нам нужно не только вернуть соответствующий HTML-код, но ипотребностикод стиля возвращается, вот и всеКлючевойКод CSS, мы можем использоватьcollect()функция для извлечения ключевого кода CSS

import { collect } from 'linaria/server';

const css = fs.readFileSync('./dist/styles.css', 'utf8');
const html = ReactDOMServer.renderToString(<App />);
const { critical, other } = collect(html, css);

// critical – returns critical CSS for given html
// other – returns the rest of styles

collect()В соответствии с атрибутом класса элемента будет извлечен используемый код CSS, чтобы его можно было вернуть с помощью html.

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

предупреждать

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

следовать за

linaria/laderбыл переименован@linaria/webpack4-loader