手写 JSX 编译器实战:React 面试高频题深度解析

97 阅读2分钟

一、项目背景

在 React 面试中,手写 JSX 编译器是高频考点。面试官常常会问:“JSX 到底是怎么变成 JS 的?”“能不能不用 Babel 实现一个简单的 JSX 转换?”
本项目以最小可运行单元,演示了 JSX 到 JS 的转换过程,帮助你彻底搞懂底层原理,轻松应对面试。

二、目录结构与文件说明

compile_jsx/
├── 1.jsx           // 简单 JSX 示例
├── 1.js            // 1.jsx 编译后的 JS
├── 2.jsx           // 复杂 JSX 示例(嵌套、属性)
├── 2.js            // 2.jsx 编译后的 JS
├── .babelrc        // Babel 配置,启用 JSX 转换
├── package.json    // 依赖与脚本
├── pnpm-lock.yaml  // pnpm 锁定文件
├── readme.md       // 项目说明

三、JSX 到 JS 的转换原理

JSX 其实不是浏览器原生支持的语法,而是 React 社区提出的一种“语法糖”。
它最终会被 Babel 等工具编译为 React.createElement 形式的 JavaScript 代码。

1. JSX 示例

const element = <h1>Hello, world!</h1>;

上述代码用Babel编译后,输出以下代码:

const element = (
  <div>
    <h1>Title</h1>
    <p>内容</p>
    <span className="red">红色</span>
  </div>
);

2. JS

const element = React.createElement("h1", null, "Hello, world!");

编译输出为:

const element = React.createElement("div", null,
  React.createElement("h1", null, "Title"),
  React.createElement("p", null, "内容"),
  React.createElement("span", { className: "red" }, "红色")
);

可以看到,JSX 语法被 Babel 转换成了嵌套的 React.createElement 调用。

四、Babel 配置详解

项目根目录下的 .babelrc 文件内容如下:

{
  "presets": ["@babel/preset-react"]
}
  • @babel/preset-react 负责将 JSX 语法转换为 React.createElement 形式。
  • 你也可以自定义 pragma,比如转成 h(),但这里保持 React 默认。

五、如何运行与体验

  1. 安装依赖(推荐 pnpm,npm/yarn 也可):

    pnpm install
    
  2. 使用 Babel 编译 JSX 文件:

    npx babel 1.jsx -o 1.js
    npx babel 2.jsx -o 2.js
    
  3. 查看生成的 JS 文件,理解每一步的转换。

  4. 你也可以在 package.json 里配置 script,批量编译:

    "scripts": {
      "build": "babel 1.jsx -o 1.js && babel 2.jsx -o 2.js"
    }
    

    然后运行:

    pnpm run build
    

六、面试延伸与思考

  1. JSX 为什么不是 JS?
    JSX 需要编译,是为了让开发体验更好,但本质上它不是浏览器原生支持的 JS 语法。

  2. 手写 JSX 编译器的思路?
    其实就是把 <tag>内容</tag> 结构转成 createElement(tag, props, ...children)
    可以用正则、AST 工具(如 babel-parser)实现。

  3. Babel 的作用?
    Babel 作为转译器,能把新语法(如 JSX、ES6+)转成浏览器能识别的老 JS 代码。

  4. React.createElement 的参数?

    • 第一个参数:标签名或组件
    • 第二个参数:属性对象
    • 第三个及以后参数:子节点
  5. 如何自定义 JSX 转换目标?
    Babel 支持自定义 pragma,比如转成 h(),适用于 Preact、Vue JSX 等场景。

七、总结

  • 本项目用最简代码,完整演示了 JSX 到 JS 的转换过程。
  • 理解底层原理,有助于面试答题和日常开发调试。
  • 推荐大家动手试试,甚至可以尝试自己写一个 mini JSX 转换器!