React v16.0

26 Сентября, 2017. Andrew Clark(Андрей Кларк)

Мы рады объявить о выпуске React v16.0! Среди изменений есть некоторые давние запросы возможностей, в том числе фрагменты, границы ошибок, порталы, поддержка пользовательских атрибутов DOM, улучшенная отрисовка на стороне сервера и уменьшенный размер файла.

Новые типы возврата метода отрисовки: фрагменты и строки

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


Код
    
  render() {
    // Теперь не нужно оборачивать список элементов в дополнительный элемент!
    return [
      // Не забывайте про ключи :)
      <li key="A">First item</li>,
      <li key="B">Second item</li>,
      <li key="C">Third item</li>,
    ];
  }
  

В будущем мы, скорее всего, добавим специальный синтаксис фрагментов в JSX, который не требует ключей.

Мы также добавили поддержку возврата строк:


Код
    
  render() {
    return 'Look ma, no spans!';
  }
  

См. Полный список поддерживаемых типов возвращаемых данных.

Улучшенная обработка ошибок

Ранее ошибки во время отрисовки могли приводить React в поврежденное состояние, создавая загадочные сообщения об ошибках и требуя обновления страницы для восстановления. Для решения этой проблемы в React 16 используется более устойчивая стратегия обработки ошибок. По умолчанию, если ошибка возникает внутри методов отрисовки компонента или жизненного цикла, все дерево компонентов размонтируется из корня. Это предотвращает отображение поврежденных данных. Однако, вероятно, это не идеально для удобства работы пользователя.

Вместо того, чтобы размонтировать все приложение каждый раз, когда есть ошибка, вы можете использовать границы ошибок. Границы ошибок - это специальные компоненты, которые отлавливают ошибки внутри своего поддерева и отображают резервный интерфейс на своем месте. Подумайте о границах ошибок, по аналогии с блоками try-catch, но для компонентов React.

Для получения дополнительной информации ознакомьтесь с нашим предыдущим постом об обработке ошибок в React 16 .

Порталы

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


Код
    
  render() {
    // React не создает новый div. Он отрисовывает потомок внутри `domNode`.
    // `domNode` - какой-нибудь валидный DOM-узел, независимо от его местоположения в дереве DOM.
    return ReactDOM.createPortal(
      this.props.children,
      domNode,
    );
  }
  

См. Полный пример в документации для порталов.

Улучшенная отрисовка на стороне сервера

React 16 включает полностью переписанную серверную отрисовку. Она очень быстрая. Она поддерживает потоки, поэтому вы можете быстрее отправлять байты клиенту. И благодаря новой стратегии упаковки, которая компилирует process.env проверки (верьте или нет, чтение process.env в Node очень медленное!), Вам больше не нужно связывать React, чтобы получить хорошую производительность серверной отрисовки.

Главный член команды, Саша Айкин, написал замечательную статью, в которой описываются улучшения SSR в React 16. Согласно синтетическим бенчмаркам Саши, серверная отрисовка в React 16 примерно в три раза быстрее, чем в React 15. «Если сравнивать React 15 со скомпилированным process.env, то в Node 4 наблюдается улучшение в 2.4 раза, в Node 6 – в 3 раза, и в целых 3,8 раз в новом релизе Node 8.4. И если вы сравните React 15 без компиляции, React 16 имеет прирост в SSR на целый порядок величины в последней версии Node! »(Саша обращает внимание на то, что эти цифры основаны на синтетических бенчмарках и могут не отражать реальную производительность.)

Кроме того, React 16 лучше увлажняет серверный HTML-код, когда тот достигает клиента. Больше не требуется, чтобы начальная отрисовка точно соответствовала результату с сервера. Вместо этого он попытается повторно использовать как можно большую часть существующего DOM. Больше никаких контрольных сумм! В целом, мы не рекомендуем вам отображать на клиенте контент, отличный от серверного, но это может быть полезно в некоторых случаях (например, временные метки). Однако опасно иметь недостающие узлы в серверном рендеринге, поскольку они могут быть пересозданы с неправильными атрибутами.

Подробнее см. Документацию для ReactDOMServer.

Поддержка пользовательских атрибутов DOM

Вместо того, чтобы игнорировать нераспознанные HTML и SVG атрибуты, React теперь передаст их в DOM . Это дает дополнительное преимущество, позволяя нам избавиться от большей части белого списка атрибутов React, что приводит к уменьшению размеров файлов.

Уменьшенный размер файла

Несмотря на все эти дополнения, React 16 на самом деле меньше по сравнению с 15.6.1!

  • react имеет размер 5.3 kb (2.2 kb - архив gzip), в сравнении с 20.7 kb (6.9 kb - архив gzip).
  • react-dom имеет размер 103.7 kb (32.6 kb - архив gzip), в сравнении с 141 kb (42.9 kb - архив gzip).
  • react + react-dom имеет размер 109 kb (34.8 kb - архив gzip), в сравнении с 161.7 kb (49.8 kb - архив gzip).

Все это в сумме имеет итоговое уменьшение 32% по сравнению с предыдущей версией.

Разница в размерах частично объясняется изменением процесса упаковки. Теперь React использует Rollup для создания плоских связок для каждого из своих различных целевых форматов, что приводит к выигрышу в размере и производительности. Формат плоской связки также означает, что влияние React на размер связки приблизительно согласовано, независимо от того, как вы собираете свое приложение, будь то с помощью Webpack, Browserify, предварительно построенных связок UMD или любой другой системы.

MIT Лицензия

В случае, если вы пропустили этот пост, React 16 доступен под лицензией MIT. Мы также опубликовали React 15.6.2 под MIT, для тех, кто не может обновиться сразу.

Новая архитектура ядра

React 16 - первая версия React, построенная построенная на новой архитектуре ядра под кодовым названием «Fiber». Вы можете прочитать все об этом проекте в блоге технической поддержки Facebook. (Спойлер: мы переписали React!)

Fiber отвечает за большинство новых функций в React 16, таких как границы ошибок и фрагменты. В течение следующих нескольких релизов вы можете ожидать больше новых возможностей, так как мы начнем полностью раскрывать потенциал React.

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

Эта демонстрация дает общее представление о типах проблем, которые может решить асинхронный рендеринг.

Мы считаем, что асинхронный рендеринг - это важная задача и представляет будущее React. Чтобы сделать миграцию на v16.0 максимально гладкой, мы пока не можем позволить использовать какие-либо асинхронные возможности, но мы рады начать разворачивать их в ближайшие месяцы. Будьте на связи!

Установка

React v16.0.0 доступен в реестре npm.

Чтобы установить React 16 с помощью Yarn, выполните:


Код
    
  yarn add [email protected]^16.0.0 [email protected]^16.0.0
  

Чтобы установить React 16 с помощью npm, выполните:


Код
    
  npm install --save [email protected]^16.0.0 [email protected]^16.0.0
  

Мы также предоставляем сборки UMD React через CDN:


Код
    
  <script crossorigin src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
  <script crossorigin src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
  

Подробные инструкции по установке см. В документации.

Апгрейд

Несмотря на то, что React 16 включает значительные внутренние изменения, с точки зрения модернизации вы можете представлять себе это, как и любой другой крупный релиз React. Мы обслуживаем React 16 для пользователей Facebook и Messenger.com с начала этого года, и мы выпустили несколько бета и релиз версий-кандидатов, чтобы избавиться от дополнительных проблем. За небольшими исключениями, если ваше приложение работает с версией 15.6 без каких-либо предупреждений, оно должно работать и в версии 16.

Новый список устаревших элементов

Гидрация контейнера, отрисованного сервером, теперь имеет явный API. Если вы восстанавливаете отрисованный сервером HTML, используйте ReactDOM.hydrate вместо ReactDOM.render. Продолжайте использовать ReactDOM.render, если вы просто выполняете отрисовку на стороне клиента.

Дополнения React

Как было объявлено ранее, мы прекратили поддержку React Addons. Мы ожидаем, что последняя версия каждого дополнения (за исключением action-addons-perf, см. Ниже) будет работать в обозримом будущем, но мы больше не будем публиковать дополнительные обновления.

Обратитесь к предыдущему объявлению о предложениях по миграции.

response-addons-perf больше не работает вообще в React 16. Вероятно, в будущем мы выпустим новую версию этого инструмента. Тем временем вы можете использовать инструменты производительности вашего браузера для профилирования компонентов React.

Повреждающие изменения

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

  • React 15 имел ограниченную недокументированную поддержку границ ошибок, используя unstable_handleError. Этот метод был переименован в componentDidCatch. Вы можете использовать модификацию кода для автоматической миграции на новый API.
  • ReactDOM.render и ReactDOM.unstable_renderSubtreeIntoContainer теперь возвращают null, если вызваны изнутри метода жизненного цикла. Чтобы обойти это, вы можете использовать порталы или ссылки refs.
  • setState:
    • Вызов setState со значением null больше не вызывает обновление. Это позволяет вам принять решение в функции обновления, нужно ли вам провести переотрисовку компонента.
    • Вызов setState непосредственно в методе render всегда вызывает обновление. Раньше это было не так. Независимо от этого, вы не должны вызывать setState из метода рендеринга.
    • setState коллбэки (второй аргумент) теперь запускаются сразу после componentDidMount / componentDidUpdate, а не после того, как все компоненты были отрисованы.
  • При замене <A/> на <B/>, B.componentWillMount теперь всегда вызывается до A.componentWillUnmount. Раньше A.componentWillUnmount мог сработать первым в некоторых случаях.
  • Раньше изменение ссылки на компонент всегда уничтожало ссылку до вызова метода отрисовки компонента. Теперь мы изменяем ссылку ref позже, когда применяются изменения к DOM.
  • Небезопасно повторно переотрисовывать в контейнер, который был изменен чем-то иным, чем React. Ранее в некоторых случаях это работало, но никогда не поддерживалось. Сейчас в такой ситуации мы выдаем предупреждение. Чтобы этого избежать вы должны очистить деревья компонентов, используя ReactDOM.unmountComponentAtNode. См. этот пример .
  • Метод жизненного цикла componentDidUpdate больше не получает параметр prevContext. (См. #8631 )
  • Поверхностная отрисовка больше не вызывает componentDidUpdate, потому что ссылки DOM недоступны. Это делает её совместимой с componentDidMount (который не вызывается в предыдущих версиях).
  • Поверхностная отрисовка больше не реализует unstable_batchedUpdates.
  • ReactDOM.unstable_batchedUpdates теперь получает только один дополнительный аргумент после метода обратного вызова.

Упаковка

  • Больше нет react/lib/* и react-dom/lib/* Даже в средах CommonJS, React и ReactDOM предварительно скомпилированы в отдельные файлы («плоские связки»). Если вы ранее полагались на недокументированные внутренние возможности React, и они больше не работают, сообщите нам о вашем конкретном случае в новой проблеме, и мы попытаемся найти для вас стратегию миграции.
  • Больше нет react-with-addons.js. Все совместимые аддоны публикуются отдельно в npm и имеют однофайловые браузерные версии, если они вам нужны.
  • Устаревшие элементы, введенные в 15.x, были удалены из пакета ядра. React.createClass теперь доступен как create-react-class, React.PropTypes как prop-types, React.DOM как react-dom-factories, react-addons-test-utils как react-dom/test-utils и поверхностная отрисовка как react-test-renderer/shallow. Смотрите сообщения в блогах 15.5.0 и 15.6.0 для инструкций по переносу кода и автоматизированных кодовых модулей.
  • Имена и пути к однофайловым браузерным сборкам изменились, чтобы подчеркнуть разницу между сборками development и production. Например:
    • react/dist/react.js => react/umd/react.development.js
    • react/dist/react.min.js => react/umd/react.production.min.js
    • react-dom/dist/react-dom.js => react-dom/umd/react-dom.development.js
    • react-dom/dist/react-dom.min.js => react-dom/umd/react-dom.production.min.js

Требования к JavaScript среде

React 16 зависит от типов коллекций Map и Set. Если вы поддерживаете старые браузеры и устройства, которые не могут предоставить их нативно (например, IE < 11), подумайте о включении глобального полифилла в ваше приложение, например core-js или babel-polyfill.

Среда с полифилом для React 16, использующая core-js для поддержки старых браузеров может выглядеть так:


Код
    
  import 'core-js/es6/map';
  import 'core-js/es6/set';

  import React from 'react';
  import ReactDOM from 'react-dom';

  ReactDOM.render(
    <h1>Hello, world!</h1>,
    document.getElementById('root')
  );
  

React также зависит от requestAnimationFrame (даже в тестовых средах). Вы можете использовать пакет raf для подключения requestAnimationFrame:


Код
    
  import 'raf/polyfill';
  

Благодарности

Как всегда, этот релиз был бы невозможен без наших open source контрибьюторов. Спасибо всем, кто пофиксил баги, открыл PR-ы, ответил на вопросы, написал документацию и многое другое!

Особая благодарность нашим основным контрибьюторам, сделавшим героические усилия за последние несколько недель в течение цикла предрелиза: Брэндону Дайлу, Джейсону Куэнсу, Натану Хунзакеру и Саше Айкину.