Skip to content

JSX 在 Bun 中的使用

JSX 简介

JSX(JavaScript XML)是一种 JavaScript 的语法扩展,允许在 JavaScript 代码中编写类似 HTML 的标记。Bun 内置支持 .jsx.tsx 文件,无需额外配置即可运行。

INFO

Bun 的内部转译器会在执行前将 JSX 语法转换为普通的 JavaScript,这个过程对开发者是透明的。

JSX 基本示例

下面是一个简单的 React 组件示例:

tsx
// 一个简单的 React 组件示例
function Component(props: {message: string}) {
  return (
    <body>
      <h1 style={{color: 'red'}}>{props.message}</h1>
    </body>
  );
}

console.log(<Component message="Hello world!" />);

在上面的代码中,我们定义了一个接收 `message` 属性的组件,并在 `h1` 标签中显示这个消息。高亮部分是 JSX 语法。

JSX 配置选项

Bun 会自动读取项目中的 tsconfig.jsonjsconfig.json 配置文件来确定如何处理 JSX 转换。如果不想使用这些配置文件,也可以在 bunfig.toml 中定义以下选项。

JSX 转换过程

    JSX代码           配置选项            转换结果
    ┌────┐           ┌────┐            ┌────┐
    │<Div>│  ──────► │jsx  │  ──────►  │普通JS│
    └────┘           └────┘            └────┘

jsx 选项

jsx 选项决定了 JSX 构造如何转换为普通 JavaScript。下表展示了不同 jsx 值对于同一个简单组件的转换结果:

tsx
<Box width={5}>Hello</Box>
配置选项转换输出说明
"react"import { createElement } from "react"; createElement("Box", { width: 5 }, "Hello");使用 React 的 createElement 函数
"react-jsx"import { jsx } from "react/jsx-runtime"; jsx("Box", { width: 5, children: "Hello" });使用 React 17+ 的新 JSX 转换
"react-jsxdev"import { jsxDEV } from "react/jsx-dev-runtime"; jsxDEV("Box", { width: 5, children: "Hello" }, undefined, false, undefined, this);开发环境专用,包含额外的调试信息
"preserve"<Box width={5}>Hello</Box>保留 JSX 语法不转换(Bun 目前不支持)

> `jsxDEV` 是 React 开发版本使用的特殊函数,它包含额外的有效性检查和调试工具,但运行速度较慢。

jsxFactory 选项

WARNING

仅当 jsx 设置为 react 时适用。

此选项指定用于表示 JSX 构造的函数名称。默认值是 "createElement"。这对于使用不同函数名的库(如 Preact 使用 "h")非常有用。

配置选项转换输出
{ "jsx": "react", "jsxFactory": "h" }import { h } from "react"; h("Box", { width: 5 }, "Hello");

jsxFragmentFactory 选项

WARNING

仅当 jsx 设置为 react 时适用。

此选项指定用于表示 JSX 片段(如 <>Hello</>)的函数名称。默认值是 "Fragment"

示例:

配置:

json
{
  "jsx": "react",
  "jsxFactory": "myjsx",
  "jsxFragmentFactory": "MyFragment"
}

输入代码:

tsx
<>Hello</>

转换后:

tsx
import { myjsx, MyFragment } from "react";
myjsx(MyFragment, null, "Hello");

jsxImportSource 选项

WARNING

仅当 jsx 设置为 react-jsxreact-jsxdev 时适用。

此选项指定将从中导入组件工厂函数(createElementjsxjsxDEV 等)的模块。默认值是 "react"。在使用 Preact 等组件库时通常需要设置此选项。

常见配置示例:

json
{
  "jsx": "react-jsx"
  // jsxImportSource 未定义,默认为 "react"
}
json
{
  "jsx": "react-jsx",
  "jsxImportSource": "preact"
}

转换效果对比:

配置转换输出
React 默认import { jsx } from "react/jsx-runtime"; jsx("Box", { width: 5, children: "Hello" });
Preact 配置import { jsx } from "preact/jsx-runtime"; jsx("Box", { width: 5, children: "Hello" });

JSX 文件级设置:pragma 指令

所有上述配置选项都可以通过特殊注释(pragma)在单个文件中设置。这使得您可以针对特定文件覆盖全局配置。

Pragma 注释等效配置
// @jsx h{ "jsxFactory": "h" }
// @jsxFrag MyFragment{ "jsxFragmentFactory": "MyFragment" }
// @jsxImportSource preact{ "jsxImportSource": "preact" }

JSX 在 Bun 中的增强功能

更好的日志输出

Bun 为 JSX 实现了特殊的日志功能,使调试变得更容易。例如:

tsx
import { Stack, UserCard } from "./components";

console.log(
  <Stack>
    <UserCard name="Dom" bio="街头赛车手,科罗娜爱好者" />
    <UserCard name="Jakob" bio="超级间谍,Dom的秘密兄弟" />
  </Stack>,
);

当您使用 console.log 打印上述组件时,Bun 会以易读的树形式显示组件结构:

<Stack>
  <UserCard name="Dom" bio="街头赛车手,科罗娜爱好者" />
  <UserCard name="Jakob" bio="超级间谍,Dom的秘密兄弟" />
</Stack>

这种可视化的日志输出大大提高了开发过程中的调试效率!

属性简写(Prop Punning)

Bun 运行时支持 JSX 的"属性简写"语法。当变量名与属性名相同时,这种简写语法非常有用。

问题陈述: 在 React 组件中,我们经常需要将同名变量传递给属性,导致代码重复。

解决方案:

tsx
function Div(props: {className: string;}) {
  const {className} = props;

  // 传统方式
  return <div className={className} />;

  // 使用属性简写
  return <div {className} />;  // 更简洁!
}

分析:

  • 传统方式需要写两次 className:一次是属性名,一次是变量名
  • 使用属性简写语法,只需写一次变量名,代码更简洁
  • 这种语法特别适合需要传递多个属性的场景
高级用例:多属性简写
tsx
function UserProfile(props) {
  const {name, age, email, avatar} = props;

  // 使用属性简写传递多个属性
  return (
    <Profile
      {name}
      {age}
      {email}
      {avatar}
    />
  );
}

JSX 转换原理总结

┌────────────────────────────────────────────┐
│                                            │
│  JSX文件(.jsx/.tsx)  ──┐                   │
│                        │                   │
│                        ▼                   │
│  ┌──────────────────────────────────┐      │
│  │ Bun内部转译器                     │      │
│  │ ├─ 读取配置:                     │      │
│  │ │  ├─ tsconfig.json             │      │
│  │ │  ├─ jsconfig.json             │      │
│  │ │  └─ bunfig.toml               │      │
│  │ │                               │      │
│  │ └─ 应用转换规则                   │      │
│  └───────────────┬──────────────────┘      │
│                  │                         │
│                  ▼                         │
│  普通JavaScript  ──► 执行                  │
│                                            │
└────────────────────────────────────────────┘

实践建议

  1. 选择合适的 JSX 转换模式

    • 对于 React 17 及以上版本,推荐使用 "react-jsx"
    • 开发环境可考虑使用 "react-jsxdev" 获得更好的调试体验
  2. 库兼容性

    • 使用 Preact 时,设置 "jsxImportSource": "preact"
    • 使用其他库时,查阅相关文档了解所需配置
  3. 性能考量

    • 生产环境避免使用 "react-jsxdev",因为它包含额外的调试信息,会影响性能
    • 开发环境可以利用 Bun 的 JSX 日志增强功能进行更高效的调试

理解 JSX 转换的工作原理对于排查问题和优化应用程序至关重要。确保在项目中正确配置 JSX 相关选项,以获得最佳的开发体验和运行效率。