В React 17 Release Candidate появляется новый способ трансформации JSX. С ним, в бандле, не понадобится сам Реакт, хотя для использования хуков он всё ещё нужен. Это и есть основной бенефит нового механизма. Под катом краткий перевод статьи в блоге ReactJS.
Так как браузеры не понимают JSX “из коробки”, разработчики полагаются на компиляторы типа Babel или Typescript, чтобы трансформировать JSX в обычный JS. В React 17 Release Candidate появился новый, опциональный механизм трасформации JSX в JS.
Вот его преимущества:
(Возможно я не совсем точно перевёл — вот оригинал: It will enable future improvements that reduce the number of concepts you need to learn React)
Апгрейд никак не меняет сам JSX и все компиляторы как работали так и будут работать. Нет никаких планов по отказу от них. Планируется поддержка нового механизма JSX Transform для старых версий Реакт: 16.х, 15.х, 14.х, вот здесь инструкции для апгрейда.
Старая JSX трасформация работала следующим образом:
Код
Трасформировался в
Но это не супер и вот почему:
Чтобы это решить в React 17 появляются две новые точки входа предназначенные для использования другими инструментами такими как Babel и Typescript и теперь вместо трансформации в React.createElement импортируются и вызываются новые функции из пакета React.
Предположим ваш код выглядел вот так:
После новой трансформации он будет выглядеть вот так:
Новый механизм не импортирует React, хотя он всё ещё нужен для работы хуков.
Новая трансформация полностью совместима со всем существующим JSX кодом, ничего менять не придётся. Вот здесь технические подробности работы новой трансформации JSX.
Если не готовы апгрейдить или используете JSX для других библиотек, не беспокойтесь, старая трансформация не будет удалена и будет поддерживаться.
Для апгрейда нужны две вещи:
Create React App
Create React App поддержка будет в релизе v4.0 сейчас он в бета тестировании (на 22.09.20)
Next.js
Next.js v9.5.3+ уже использует новую Реакт трансформацию для совместимых версий.
Gatsby
Gatsby v2.24.5+ уже использует новую Реакт трансформацию для совместимых версий.
Ручная настройка Babel
Поддержка с версии v7.9.0 и выше.
Если вы используете babel/plugin-transform-react-jsx:
# npm
# yarn
Если вы используете babel/preset-react:
# npm
# yarn
Сейчас для трансформации JSX, в babel/plugin-transform-react-jsx и в babel/preset-react, по умолчанию включена опция {«runtime»: «classic»} это старая версия трансформации. Для включения новой трансформации нужна опция {«runtime»: «automatic»}
Если вы используете babel/preset-react:
Если вы используете babel/plugin-transform-react-jsx:
Начиная с версии Babel 8, «automatic» будет значением по умолчанию для обоих плагинов. Вот здесь более подробная документация @babel/plugin-transform-react-jsx and @babel/preset-react.
ESLint
Если у вас плагин eslint-plugin-react, то правила react/jsx-uses-react и react/react-in-jsx-scope больше не нужны и их можно удалить.
TypeScript
Поддержка JSX трансформации с версии 4.1 beta.
Flow
Поддержка JSX трансформации с версии 0.126.0 и выше.
Поскольку новая JSX трансформация автоматически импортирует react/jsx-runtime, React больше не нужен в области видимости для использования JSX. Неиспользуемые импорты это не критично, но если хотите удалить, рекомендуется использовать скрипт codemod.
В результате:
Код:
Будет заменён на:
Если вы используете что то другое в реакте (например хук), то в коде появится именованный импорт:
Код
Заменится на код:
Удаление неиспользуемого импорта поможет подготовиться к следующим версиям Реакта (не 17) в которых будет поддержка ES модулей и не будет дефолтного экспорта.
Мы благодарим команды Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, и Flow за их помощь в интеграции нового механизма JSX трансформации. Мы также благодарим сообщество Реакт за их отзывы и обсуждения RFC.
Что такое JSX Трансформация
Так как браузеры не понимают JSX “из коробки”, разработчики полагаются на компиляторы типа Babel или Typescript, чтобы трансформировать JSX в обычный JS. В React 17 Release Candidate появился новый, опциональный механизм трасформации JSX в JS.
Вот его преимущества:
- Использование JSX без импорта Реакт
- В зависимости от настроек бандл может слегка уменьшиться
- В будущем будут доступны фичи для упрощения работы с реактом
(Возможно я не совсем точно перевёл — вот оригинал: It will enable future improvements that reduce the number of concepts you need to learn React)
Апгрейд никак не меняет сам JSX и все компиляторы как работали так и будут работать. Нет никаких планов по отказу от них. Планируется поддержка нового механизма JSX Transform для старых версий Реакт: 16.х, 15.х, 14.х, вот здесь инструкции для апгрейда.
Что изменилось
Старая JSX трасформация работала следующим образом:
Код
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
Трасформировался в
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
Но это не супер и вот почему:
- Так как JSX компилируется в React.createElement, React должен быть в области видимости
- Есть несколько вариантов улучшить скорость и упростить, которые блокирует React.createElement
Чтобы это решить в React 17 появляются две новые точки входа предназначенные для использования другими инструментами такими как Babel и Typescript и теперь вместо трансформации в React.createElement импортируются и вызываются новые функции из пакета React.
Предположим ваш код выглядел вот так:
function App() {
return <h1>Hello World</h1>;
}
После новой трансформации он будет выглядеть вот так:
// Inserted by a compiler (don't import it yourself!)
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
Новый механизм не импортирует React, хотя он всё ещё нужен для работы хуков.
Новая трансформация полностью совместима со всем существующим JSX кодом, ничего менять не придётся. Вот здесь технические подробности работы новой трансформации JSX.
Как апгрейдить
Если не готовы апгрейдить или используете JSX для других библиотек, не беспокойтесь, старая трансформация не будет удалена и будет поддерживаться.
Для апгрейда нужны две вещи:
- Версия Реакт с поддержкой новой трансформации. Пока что это только 17, но в будущем 16.х, 15.х и 14.х
- Совместимый компилятор (см. ниже)
Create React App
Create React App поддержка будет в релизе v4.0 сейчас он в бета тестировании (на 22.09.20)
Next.js
Next.js v9.5.3+ уже использует новую Реакт трансформацию для совместимых версий.
Gatsby
Gatsby v2.24.5+ уже использует новую Реакт трансформацию для совместимых версий.
примечание
Если у вас в Gatsby вот такая ошибка после апгрейда на 17.0.0-rc.2, запустите npm update
Ручная настройка Babel
Поддержка с версии v7.9.0 и выше.
Если вы используете babel/plugin-transform-react-jsx:
# npm
npm update @babel/core @babel/plugin-transform-react-jsx
# yarn
yarn upgrade @babel/core @babel/plugin-transform-react-jsx
Если вы используете babel/preset-react:
# npm
npm update @babel/core @babel/preset-react
# yarn
yarn upgrade @babel/core @babel/preset-react
Сейчас для трансформации JSX, в babel/plugin-transform-react-jsx и в babel/preset-react, по умолчанию включена опция {«runtime»: «classic»} это старая версия трансформации. Для включения новой трансформации нужна опция {«runtime»: «automatic»}
Если вы используете babel/preset-react:
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
Если вы используете babel/plugin-transform-react-jsx:
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
Начиная с версии Babel 8, «automatic» будет значением по умолчанию для обоих плагинов. Вот здесь более подробная документация @babel/plugin-transform-react-jsx and @babel/preset-react.
Примечание
Если вы используете не Реакт, вы можете использовать опцию importSource для импорта, если конечно ваша библиотека предоставляет точки входа. Вы так же можете продолжать использовать классическую трансформацию, которая будет поддерживаться и дальше.
ESLint
Если у вас плагин eslint-plugin-react, то правила react/jsx-uses-react и react/react-in-jsx-scope больше не нужны и их можно удалить.
{
// ...
"rules": {
// ...
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}
TypeScript
Поддержка JSX трансформации с версии 4.1 beta.
Flow
Поддержка JSX трансформации с версии 0.126.0 и выше.
Как убрать неиспользуемые импорты React
Поскольку новая JSX трансформация автоматически импортирует react/jsx-runtime, React больше не нужен в области видимости для использования JSX. Неиспользуемые импорты это не критично, но если хотите удалить, рекомендуется использовать скрипт codemod.
cd your_project
npx react-codemod update-react-imports
В результате:
- Удалятся все неиспользуемые импорты React
- Изменятся все импорты типа import React from «react» на именованные import { useState } from «react». Это предпочтительный способ импорта. Codemod не затронет импорты типа import * as React from «react», это тоже валидный импорт и в 17 версии он будет работать, но в дальнейшем мы будем просить избавляться от него
Код:
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
Будет заменён на:
function App() {
return <h1>Hello World</h1>;
}
Если вы используете что то другое в реакте (например хук), то в коде появится именованный импорт:
Код
import React from 'react';
function App() {
const [text, setText] = React.useState('Hello World');
return <h1>{text}</h1>;
}
Заменится на код:
import { useState } from 'react';
function App() {
const [text, setText] = useState('Hello World');
return <h1>{text}</h1>;
}
Удаление неиспользуемого импорта поможет подготовиться к следующим версиям Реакта (не 17) в которых будет поддержка ES модулей и не будет дефолтного экспорта.
Благодарности
Мы благодарим команды Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, и Flow за их помощь в интеграции нового механизма JSX трансформации. Мы также благодарим сообщество Реакт за их отзывы и обсуждения RFC.
Finesse
В начале статьи я подумал, что наконец-то
React.createElement
будет вызываться во время транспиляции, а не в рантайме (результат вызова этой функции — простой объект). А оказалось, что просто поменяли название импортируемого пакета.artemu78 Автор
я так понимаю — главное к чему идут это возможность апгрейдить реакт по частям, ради этого и разбивают библиотеку, об этом у них предыдущая статья reactjs.org/blog/2020/08/10/react-v17-rc.html
anonymous
Плюс хотят избавиться от старых косяков — forwardRef, ручное вытаскивание key из пропсов и т.д.
https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md