v3.1.0: значительное повышение производительности и поддержка потокового рендеринга на стороне сервера.

Новый механизм внедрения CSS означает более быстрый рендеринг на стороне клиента в производственной среде, а поддержка потокового рендеринга на стороне сервера обеспечивает более быстрое получение первого байта! 🔥🔥

Более быстрое внедрение CSS в производство

Этот патч готовился давно и имеет долгую историю. Почти полтора года назад (!) Сунил Пай нашел новый и широко неизвестный DOM API: insertRule. Он позволяет вставлять CSS из JavaScript в DOM с невероятной скоростью; Единственным недостатком является то, что стили нельзя редактировать с помощью DevTools браузера.

Когда Глен и Макс впервые создавали стилизованные компоненты, они были на 100% ориентированы на опыт разработчиков. Для небольших приложений проблем с производительностью было мало, поэтому они решили не использовать insertRule. По мере того, как распространение росло, и люди использовали стилизованные компоненты для более крупных приложений, внедрение стиля оказалось узким местом для людей с очень динамичными вариантами использования.

Благодаря Райану Шверсу, фронтенд-инженеру Reddit, styled-components v3.1.0 теперь по умолчанию использует insertRule в производстве.

Мы провели несколько тестов с предыдущей версией (v3.0.2) и новой с insertRule, и результаты оказались даже лучше наших (и без того высоких) ожиданий:

Первоначальное время монтирования тестового приложения было сокращено примерно в 10 раз, а время повторного рендеринга - примерно в 20 раз!

Обратите внимание, что тесты представляют собой стресс-тестирование библиотеки и не являются репрезентативными для реального приложения. Хотя ваше приложение (вероятно) не будет монтироваться в 10 раз быстрее, время до первого взаимодействия снизилось на сотни миллисекунд в одном из наших производственных приложений!

Вот как стилизованные компоненты выдерживают сравнение с другими основными фреймворками React CSS-in-JS в этих тестах:

Хотя это (пока) не самый быстрый фреймворк CSS-in-JS в микротестах, он лишь ненамного медленнее самых быстрых - до такой степени, что его уже нельзя считать узким местом. Реальные результаты очень обнадеживают, и мы с нетерпением ждем, когда вы все поделитесь своими выводами!

Потоковый рендеринг на стороне сервера

Потоковый рендеринг на стороне сервера был представлен в React v16. Он позволяет серверу приложений отправлять HTML, когда он становится доступным, пока React все еще выполняет рендеринг, что ускоряет время до первого байта (TTFB) и позволяет вашему серверу Node обрабатывать Противодавление проще.

Это плохо сочетается с CSS-in-JS: традиционно мы вставляем тег <style> со стилями всех ваших компонентов в <head> после завершения рендеринга React. Однако в случае потоковой передачи <head> отправляется пользователю до отрисовки каких-либо компонентов, поэтому мы больше не можем вводить в него.

Решение состоит в том, чтобы чередовать HTML с <style> блоками по мере рендеринга компонентов, а не ждать до самого конца и вводить все компоненты сразу. Поскольку это мешает ReactDOM на клиенте (присутствует HTML, за который React не несет ответственности), мы должны объединить все эти style теги обратно в <head> перед регидратацией.

Мы реализовали именно это; теперь вы можете использовать потоковый рендеринг на стороне сервера со стилями компонентов! Вот как:

import { renderToNodeStream } from 'react-dom/server'
import styled, { ServerStyleSheet } from 'styled-components'
res.write('<!DOCTYPE html><html><head><title>My Title</title></head><body><div id="root">')
const sheet = new ServerStyleSheet()
const jsx = sheet.collectStyles(<App />)
// Interleave the HTML stream with <style> tags
const stream = sheet.interleaveWithNodeStream(
  renderToNodeStream(jsx)
)
stream.pipe(res, { end: false })
stream.on('end', () => res.end('</div></body></html>'))

Позже на стороне клиента необходимо вызвать consolidateStreamedStyles() API, чтобы подготовиться к фазе регидратации React:

import ReactDOM from 'react-dom'
import { consolidateStreamedStyles } from 'styled-components'
/* Make sure you call this before ReactDOM.hydrate! */
consolidateStreamedStyles()
ReactDOM.hydrate(<App />, rootElem)

Вот и все! 💯 (дополнительные сведения см. В потоковой документации)

v3: без критических изменений

Хорошие новости! Если вы используете v2 (или даже v1), новая версия имеет обратную совместимость, и обновление должно происходить без проблем. В эти новые версии внесены десятки улучшений, поэтому, пожалуйста, ознакомьтесь с ними, и мы надеемся, что они вам и вашим посетителям понравятся!

См. Журнал изменений для получения дополнительной информации о выпуске v3.0.0 и v3.1.0.

Оставайся стильным! 💅

Обсудите этот пост в сообществе styled-components.

Спасибо Грегори Шехету за его тесты CSS-in-JS, на которые есть ссылки в этом сообщении.