结论:因为新的 JSX Transform 不再需要 React 作用域来编译 JSX 了。
React 17 引入了 全新的 JSX 转换机制(New JSX Transform),React 18 继续沿用。
👉 从 React 17+(包含 React 18)开始, JSX 编译时已经不再依赖 React 本体,因此组件文件无需必须 import React。
React 16及以前为什么必须 import React?
在 React 16 及以前,JSX 会被编译成类似这样的代码:
jsx
const element = <div>Hello</div>;
会被 Babel 编译成:
js
const element = React.createElement("div", null, "Hello");
所以:
-
JSX -> React.createElement
-
编译后的代码需要 React 全局变量
-
所以文件顶部必须写:
jsimport React from 'react';
否则 React.createElement 找不到会报错。
React 17:新的 JSX Transform
从 React 17 开始,React 引入了 新的 JSX Transform ,不再编译成 React.createElement,而是编译成更轻量的 helper 函数(由 React 自动引入)。
例如:
jsx
const element = <div>Hello</div>;
会被编译成:
js
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("div", { children: "Hello" });
特点:
- 编译结果不再需要全局 React
JSX 不再使用 React.createElement,而是用来自 react/jsx-runtime 的自动注入 helper。
- 自动引入 helper,不需要你手动写 import
Babel 或 SWC 会自动在文件里加入:
js
import { jsx } from 'react/jsx-runtime';
在 Webpack / Vite 项目中如何启用?
Vite(默认启用)
Vite 默认使用 esbuild / SWC 编译 JSX,自动启用新 JSX transform。
你不需要做任何配置。
Webpack(React 17 + Babel)
需要安装:
bash
npm i @babel/preset-react
babel.config.js:
js
module.exports = {
presets: [
['@babel/preset-react', { runtime: 'automatic' }]
]
};
runtime: 'automatic' 就是"自动注入 JSX helper"。
为什么 React 团队要这么做?
官方给出的原因:
- 更少的样板代码(boilerplate)
不用每个组件都写 import React。
- 更小的 bundle
不再频繁使用 React.createElement,helper 更轻量。
- 为未来的 React 特性(如 Server Components)铺路
新的 transform 更灵活,扩展性更好。
- 更快的编译(尤其在 Vite / ESBuild 下)
JSX => helper 的转换更简单,利于性能。