前言
学过 React 的朋友们,肯定对 JSX 十分熟悉。它是 React 中编写 UI 的主要方式,看起来像是直接在 JavaScript 里写 HTML,但实际上它的背后隐藏了许多重要的机制。今天,我们就来深入探讨 JSX 的本质、原理以及编译它的工具-Babel。
JSX到底是个啥?
JSX(JavaScript XML) 是 React 提供的一种JavaScript语法扩展,允许我们在 JavaScript 代码中编写类似 HTML 的结构。例如:
const element = <h1>Hello, React!</h1>;
虽然它看起来像 HTML,但它 并不是真正的 HTML,而是一种 JavaScript 的语法糖,最终会被转换成标准的 JavaScript 代码。
JSX背后的原理
JSX 不能独立运行
JSX 的语法(如 <div>Hello</div>)并不是原生 JavaScript 的一部分,浏览器和 JavaScript 引擎无法直接解析它,如果你尝试直接运行JSX,那么则会报语法错误,因为它不符合 JavaScript 语法规范:
-
JSX 的语法(如
<div>Hello</div>)并不是原生 JavaScript 的一部分,浏览器和 JavaScript 引擎无法直接解析它。 -
JSX 最终需要被转换为标准的 JavaScript 函数调用(如
React.createElement()),否则会报语法错误。
要让JSX能够运行的几种方法:
- 使用编译器:通过 Babel 等工具将 JSX 转为 JavaScript。
- 提供运行时环境:确保 React(或类似库如 Preact)被引入。
- 配置构建工具:例如在 Webpack 中配置
babel-loader。
JSX的编译--Babel
上面我们提到了JSX不能独立运行,它必须通过工具(如 Babel、TypeScript 或 SWC)编译成普通的 JavaScript 代码,才能运行,今天我们就对编译工具Babel进行详解,Babel也是React通常使用的将 JSX 转换为 React.createElement() 调用的方法,让我们看看Babel是具体怎么编译JSX的吧!
Babel是什么?
Babel 是一个 JavaScript 编译器,主要用于将新版本的 JavaScript(如 ES6+)或扩展语法(如 JSX)转换成浏览器广泛支持的旧版 JavaScript(如 ES5)。它通过插件系统(如 @babel/preset-react)处理 JSX,将其编译为 React.createElement() 调用,并支持语法降级、代码优化等功能,是现代前端开发(如 React、Vue 等框架)不可或缺的工具链核心。
详细步骤解析
Babel 将 JSX 转换为 React.createElement() 调用的过程可以分为以下几个关键步骤:
1. 安装必要依赖
首先需要安装 Babel 核心工具和 React 相关的预设:
pnpm install @babel/cli @babel/core @babel/preset-react -D
@babel/cli: Babel 命令行工具@babel/core: Babel 核心编译引擎@babel/preset-react: 专门处理 JSX 转换的预设
2. 配置 Babel
创建或修改 babel.config.json 文件:
{
"presets": ["@babel/preset-react"]
}
3. 编译过程详解
当 Babel 处理 JSX 文件时,会经历以下转换步骤:
3.1 解析阶段 (Parsing)
Babel 使用 Babylon 解析器将 JSX 代码解析成抽象语法树(AST)
// 原始代码
const element = <h1 className="title">Hello</h1>;
会被解析为类似这样的 AST 结构:
{
"type": "JSXElement",
"openingElement": {
"type": "JSXOpeningElement",
"name": { "type": "JSXIdentifier", "name": "h1" },
"attributes": [
{
"type": "JSXAttribute",
"name": { "type": "JSXIdentifier", "name": "className" },
"value": { "type": "StringLiteral", "value": "title" }
}
]
},
"children": [
{ "type": "JSXText", "value": "Hello" }
]
}
3.2 转换阶段 (Transformation)
@babel/preset-react 中的插件会将 JSX AST 转换为 JavaScript AST
转换规则:
- JSX 元素 →
React.createElement()调用 - 属性 → 第二个参数的对象属性
- 子元素 → 后续参数
3.3 生成阶段 (Code Generation)
将转换后的 AST 重新生成为 JavaScript 代码:
// 转换后代码
const element = React.createElement(
"h1",
{ className: "title" },
"Hello"
);
4. 执行编译
使用 Babel CLI 执行编译:
./node_modules/.bin/babel src --out-dir lib
或通过 npm script:
{
"scripts": {
"build": "babel src --out-dir lib"
}
}
5. 运行时要求
编译后的代码需要 React 运行时支持,因此需要确保:
- React 已安装 (
pnpm install react) - React 在作用域内可用 (通过 import 或全局变量)
看看我们的编译结果把!
了解了这个过程之后,所以现在你能够知道:JSX不能直接运行,它需要通过React使用Babel的工具编译。而在实际开发中,我们很少直接使用Babel的命令行工具(@babel/cli)来手动编译JSX,是因为现代前端工具链React已经帮我们自动集成了这个过程。
总结
JSX作为React的核心语法,虽然看起来像HTML,但实际上是JavaScript的语法扩展,无法被浏览器直接执行。通过本文的深入探讨,我们了解到Babel在这一转换过程中扮演着关键角色:它将JSX代码解析为AST抽象语法树,再转换为React.createElement()调用,最终生成浏览器可执行的JavaScript代码。有趣的是,在现代前端开发中,虽然我们很少直接操作Babel命令行工具,但通过create-react-app等脚手架工具和webpack等打包工具,这一编译过程已经被完美地自动化集成。理解JSX的编译原理不仅能帮助我们更好地使用React,也能在遇到相关问题时快速定位和解决,是每位React开发者都应该掌握的核心知识。