Перейти к содержимому

Emotion react что это

  • автор:

Использование Content-Security-Policy вместе с React & Emotion

Content-Security-Policy (CSP) — это HTTP заголовок, который улучшает безопасность веб-приложений за счет запрета небезопасных действий, таких как загрузка и отправка данных на произвольные домены, использование eval , inline-скриптов и т.д. В этой статье будет сделан фокус на директиве style-src и ее использование вместе с CSS-in-JS библиотекой emotion.

Кратко о CSP и style-src

Content-Security-Policy заголовок должен быть выставлен в ответе вместе с загружаемой веб-страницей (например, index.html ). Это выглядит следующим образом:

Content-Security-Policy: style-src ‘self’

style-src — это директива, которая отвечает за то, какие стили можно загружать и применять на странице. Возможные значения:

  • ‘none’ — все стили запрещены
  • ‘self’ — разрешены файлы стилей, которые загружаются с того же домена, что и основной документ (страница)
  • , например https://example.com — разрешены файлы стилей с этого домена, также допускаются wildcard (*) на месте под-домена и порта
  • ‘-‘ , например ‘sha256-ozBpjL6dxO8fsS4u6fwG1dFDACYvpNxYeBA6tzR+FY8=’ — разрешены файлы стилей и inline-стили (тег ), у которых хеш совпадает с указанным значением
  • ‘nonce-‘ , например ‘nonce-abc’ — разрешаются inline-стили, у которых атрибут nonce совпадает с указанным (в примере — abc )
  • ‘unsafe-hashes’ — разрешает inline-стили, указанные в атрибуте style строкой, например , при этом хеш значения атрибута должен совпадать с хешом, указанным в ‘-‘
  • ‘unsafe-inline’ — разрешает все inline-стили, созданные через тег
  • ‘unsafe-eval’ — разрешает добавление/изменение CSS declarations, которые приводят к парсингу строки, например, с помощью CSSStyleDeclaration.cssText

Директива может принимать несколько значений через пробел. В этом случае это трактуется как логическое «или» — при удовлетворении хотя бы одному значению стили разрешаются.

CSP и emotion

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

  1. ‘unsafe-inline’ — самая простая опция из всех. Не требует какой-либо настройки со стороны emotion . При этом мы снижаем безопасность нашего приложения, поэтому это решение можно использовать только как временное.
  2. ‘nonce-‘ — можно разрешить inline-стили, созданные emotion . Для этого нужно задать nonce при создании cache .

При использовании @emotion/react или @emotion/styled это можно сделать следующим образом:

import < CacheProvider >from "@emotion/react"; import createCache from "@emotion/cache"; export function App() < const cache = createCache(< key: 'my-app', nonce: getNonceValue(), >); return ( >  ); >

Если используется @emotion/css напрямую, то потребуется создать свой экземпляр emotion :

import createEmotion from '@emotion/css/create-instance'; export const < flush, hydrate, cx, merge, getRegisteredStyles, injectGlobal, keyframes, css, sheet, cache >= createEmotion(< key: 'my-app', nonce: getNonceValue(), >);

При использовании createEmotion потребуется поменять все места, где раньше импортировался @emotion/css на этот модуль:

// import < css >from "@emotion/css"; import < css >from "./emotion";

Передача nonce на фронтенд

Т.к. значение CSP заголовка недоступно коду, исполняемому на клиенте, то значение нужно дополнительно передать другим образом. Один из вариантов — это создание inline-скрипта со значением, которое выставляется на бекенде:

На фронтенде это можно использовать таким образом:

function getNonceValue()

Обратите внимание на type=»application/json» — таким образом браузер не считает это исполняемым кодом, и особое значение для script-src не требуется.

Как создать компонент списка с помощью Emotion

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

[…] Библиотека, предназначенная для написания стилей CSS с помощью JavaScript. Она обеспечивает мощную и предсказуемую композицию стилей в дополнение к отличному опыту разработки с такими функциями, как исходные карты, метки и утилиты для тестирования. Поддерживаются как строковые, так и объектные стили.

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

Emotion решает эту проблему, добавляя настраиваемые строки в имена классов, чтобы они не конфликтовали с другими компонентами. Ниже приведен пример HTML-код, который он может вывести.

Довольно аккуратно, да? Есть много других инструментов и рабочих процессов, которые делают нечто очень похожее, например, CSS-модули.

Обновлено: 2023-06-26 17:50:28 Вадим Дворников автор материала

Шаг 1

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

import React from 'react'; import styled from '@emotion/styled'; export const List = styled('ul')` list-style: none; padding: 0; `;

    , но и определяем, что компонент также должен отображать

      . Комбинировать разметку и стили в одном месте кажется странным, но мне нравится, насколько это просто. Это противоречит только моей ментальной модели и разделению задач между HTML, CSS и JavaScript.

    В другом компоненте мы можем импортировать и использовать его следующим образом:

    import List from 'components/list'; This is a list item.

      , который мы определили в компоненте.

    Шаг 2

      и
      с одним и тем же компонентом. Необходима также версия, которая позволяла бы помещать значок в каждый элемент списка. А именно:

    Шаг 2

      без необходимости создавать пользовательское свойство type или что-то в этом роде. Все это выглядит примерно так:

    This will render a ul. This will render an ol.

    Это странно, правда? Однако это очень удобно, потому что это означает, что нам не нужно выполнять какую-либо причудливую логику в самом компоненте только для того, чтобы изменить разметку.

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

     Item 1 Item 2 Item 3  >>Item 1 >>Item 2 >>Item 3  Item 1 Item 2 Item 3 

    Шаг 3

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

    import React from 'react'; import styled from '@emotion/styled'; export const List = styled('ul')` list-style: none; padding: 0; margin-bottom: 20px; ol& < counter-reset: numberedList; >`;

      . Часто бывает хорошей идеей просто добавить к этому элементу background: red;, чтобы убедиться, что компонент отображается правильно.

    Шаг 4

    Далее идет подкомпонент . Важно отметить, что в Sentry также используется TypeScript, поэтому, прежде чем мы определим компонент , необходимо настроить свойства:

    type ListItemProps = < icon?: React.ReactNode; children?: string | React.ReactNode; className?: string; >;

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

     >>Item 1 >>Item 2 >>Item 3 

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

    type ListItemProps = < icon?: React.ReactNode; children?: string | React.ReactNode; className?: string; >; const IconWrapper = styled('span')` display: flex; margin-right: 15px; height: 16px; align-items: center; `;

    Шаг 5

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

    И вот оно! Относительно простой компонент , созданный с помощью Emotion. Хотя после выполнения этого упражнения я все еще не уверен, что мне нравится синтаксис. Я считаю, что это делает простые вещи действительно простыми, но компоненты среднего размера намного сложнее, чем они должны быть. К тому же, это может быть чертовски запутанным для новичка, и меня это немного беспокоит.

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

    Стилизация кода React и библиотека emotion

    Стилизовать компоненты в React можно напрямую – с помощью свойства style, которое принимает объект со свойствами стиля. В большинстве случаев этого более чем достаточно. Однако в style невозможно указать более подробные значения по умолчанию в качестве отдельного свойства, а еще здесь практически отсутствует поддержка !important. К счастью, эти недостатки легко обойти.

    emotion – гибкая и высокопроизводительная библиотека CSS-in-JS. Она принимает строки и объекты, поддерживает переменные по умолчанию и расширяемые переменные, а с дополнительным плагином Babel – даже встроенные дочерние селекторы!

    Установка библиотеки emotion

    Для начала нам нужно установить зависимости, emotion и emotion-react. Это можно сделать с помощью npm:

    $ npm install —save emotion emotion-react

    $ yarn add emotion emotion-react

    Обязательно включите react-emotion в исходный код вашего компонента:

    import styled, < css >from «react-emotion»;

    Использование библиотеки emotion

    А теперь давайте поговорим о различных способах стилизации компонентов с помощью emotion.

    Самый быстрый способ начать работу с emotion – передать css в свойство className элемента или компонента.

    css принимает стили в виде строки, тегированного шаблонного литерала, объекта или массива.

    Например, вот так CSS принимает строки и объекты:

    Hooray, styles!

    В дополнение к css для создания элементов и их стилей также можно использовать styled.

    Подобно css, styled принимает строки, тегированные шаблонные литералы, объекты или массивы.

    Если вы создаете элемент с помощью styled, вы можете затем создать новые элементы со свойствами, которые позже можно использовать в стилях. Это упрощает пользовательскую настройку и повторное использование элементов кода:

    const Heading = styled("h1")` background-color: $ props.bg>; color: $ props.fg>; `;

    Этот код создает компонент Heading, который принимает свойства bg и fg – они задают цвет фона и текста:

     Heading with yellow text and a green background! 

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

    const Subheading = Heading.withComponent(«h2»);

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

     Subheading with default colors! Subheading with light green text! Subheading with light green background! 

    Как и в css, здесь вы можете задать стили в виде объекта, а не строки:

    const Quote = styled(«blockquote»)(props => ( fontSize: props.size,
    >));

    и даже включить объект стилей по умолчанию:

    const Cite = styled(«cite»)(
    fontWeight: 100
    >,
    props => ( fontWeight: props.weight
    >)
    );

    Их можно дополнительно установить при использовании компонента:

     Citation with light text! > Citation with heavy text! 

    И конечно, как мы уже говорили, библиотека emotion без проблем принимает стили через !important:

    const Footer = styled("footer")` margin-top: 50px !important; `;

    Итоги

    Только что мы рассмотрели несколько отдельных примеров использования библиотеки emotion. А теперь давайте попробуем объединить их в более связный пример. У нас получилось следующее:

    import React from "react"; import < render >from "react-dom"; import styled, < css >from "react-emotion"; const Heading = styled("h1")` background-color: $ props.bg>; color: $ props.fg>; `; const Subheading = Heading.withComponent("h2"); const Quote = styled("blockquote")(props => (< fontSize: props.size >)); const Cite = styled("cite")( < fontWeight: 100 >, props => (< fontWeight: props.weight >) ); const Footer = styled("footer")` border-top: 1px solid #ccc; color: #ccc; margin-top: 50px !important; padding-top: 20px; `; function App() < return ( 
    >
    )>> Gator Lyrics Lyrics from songs that contain the word "alligator" > See you later, alligator. After a while, crocodile. >Bill Haley
    EOF
    ); > const container = document.createElement("div"); document.body.appendChild(container); render(, container);

    Теперь вы знаете, как создавать стили в приложении React с помощью emotion.

    Приведенный выше код можно также найти в этой песочнице CodeSandbox.

    Introduction

    Emotion is a library designed for writing css styles with JavaScript. It provides powerful and predictable style composition in addition to a great developer experience with features such as source maps, labels, and testing utilities. Both string and object styles are supported.

    There are two primary methods of using Emotion. The first is framework agnostic and the second is for use with React.

    Framework Agnostic

    npm i @emotion/css 

    The @emotion/css package is framework agnostic and the simplest way to use Emotion.

    • Requires no additional setup, babel plugin, or other config changes.
    • Has support for auto vendor-prefixing, nested selectors, and media queries.
    • You simply prefer to use the css function to generate class names and cx to compose them.
    • Server side rendering requires additional work to set up
    import css > from '@emotion/css'
    const color = 'white'
    render(
    div
    className=css`
    padding: 32px;
    background-color: hotpink;
    font-size: 24px;
    border-radius: 4px;
    &:hover
    color: $color>;
    >
    `>
    >
    Hover to change color.
    div>
    )

    (Edit code to see changes)

    React

    npm i @emotion/react 

    The @emotion/react package requires React and is recommended for users of that framework if possible.

    • Best when using React with a build environment that can be configured.
    • css prop support
      • Similar to the style prop, but also has support for auto vendor-prefixing, nested selectors, and media queries.
      • Allows developers to skip the styled API abstraction and style components and elements directly.
      • The css prop also accepts a function that is called with your theme as an argument allowing developers easy access to common and customizable values.
      • Reduces boilerplate when composing components and styled with emotion.
      import css > from '@emotion/react'
      const color = 'white'
      render(
      div
      css=css`
      padding: 32px;
      background-color: hotpink;
      font-size: 24px;
      border-radius: 4px;
      &:hover
      color: $color>;
      >
      `>
      >
      Hover to change color.
      div>
      )

      (Edit code to see changes)

      npm i @emotion/styled @emotion/react 

      The @emotion/styled package is for those who prefer to use the styled.div style API for creating components.

      import styled from '@emotion/styled'
      const Button = styled.button`
      padding: 32px;
      background-color: hotpink;
      font-size: 24px;
      border-radius: 4px;
      color: black;
      font-weight: bold;
      &:hover
      color: white;
      >
      `
      render(Button>This my button component.Button>)

      (Edit code to see changes)

      Browser requirements

      Emotion supports all popular browsers and Internet Explorer 11.

      Libraries that Inspired Us

      Getting Started

      • Introduction
      • Install
      • The css Prop
      • Styled Components
      • Composition
      • Object Styles
      • Nested Selectors
      • Media Queries
      • Global Styles
      • Package Summaries

      Advanced

      • Best Practices
      • Keyframes
      • Server Side Rendering
      • Attaching Props
      • Theming
      • Labels
      • Class Names
      • CacheProvider
      • Performance
      • For Library Authors

      Tooling

      Packages

      • @emotion/react
      • @emotion/styled
      • @emotion/cache
      • @emotion/css
      • @emotion/babel-plugin
      • @emotion/eslint-plugin
      • @emotion/server
      • @emotion/jest
      • @emotion/native
      • @emotion/primitives
      • @emotion/babel-preset-css-prop

      Posts

      • Emotion 11
      • Migrating to Emotion 10

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

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