---
title: "JSX"
description: "Deno 中使用 JSX 的完整指南。了解 JSX 配置选项、自动运行时功能、开发转换,以及 Deno 为服务器端渲染优化的预编译转换。"
oldUrl:
- /deploy/manual/using-jsx/
- /runtime/manual/advanced/jsx_dom/jsx/
- /runtime/manual/advanced/jsx/
---
Deno 内置支持 `.jsx` 文件和 `.tsx` 文件中的 JSX。Deno 中的 JSX 对于服务器端渲染或为浏览器生成代码非常有用。
## 默认配置
Deno CLI 对 JSX 有默认配置,这与 `tsc` 的默认配置不同。实际上,Deno 默认使用以下 [TypeScript 编译器](https://www.typescriptlang.org/docs/handbook/compiler-options.html) 选项:
```json title="deno.json"
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment"
}
}
```
使用 `"react"` 选项时,将 JSX 转换为以下 JavaScript 代码:
```jsx
// 输入
const jsx = (
);
// 输出:
const jsx = React.createElement(
"div",
{ className: "foo" },
React.createElement(MyComponent, { value: 2 }),
);
```
## JSX 自动运行时(推荐)
在 React 17 中,React 团队添加了他们所称之为 [新 JSX 转换](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)。这增强了 JSX 转换的 API,并提供了一种机制,可以自动添加相关的 JSX 导入,以便您无需手动添加。这是推荐使用 JSX 的方式。
要使用更新的 JSX 运行时转换,请在您的 `deno.json` 中更改编译器选项。
```json title="deno.json"
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
},
"imports": {
"react": "npm:react",
"@types/react": "npm:@types/react"
}
}
```
:::note install dependencies
当您手动向 `deno.json` 文件添加导入时,请记得运行
`deno install` 来下载安装和缓存依赖。
:::
幕后的 `jsxImportSource` 设置总是会向导入说明符追加一个
`/jsx-runtime`。
```js
// 此导入将被自动插入
import { jsx as _jsx } from "react/jsx-runtime";
```
使用 `"react-jsx"` 选项将 JSX 转换为以下 JavaScript 代码:
```jsx
// 输入
const jsx = (
);
// 输出
import { jsx as _jsx } from "react/jsx-runtime";
const jsx = _jsx(
"div",
{
className: "foo",
children: _jsx(MyComponent, { value: 2 }),
},
);
```
如果您希望使用 [Preact](https://preactjs.com/) 而不是 React,您可以相应地更新 `jsxImportSource` 值。
```diff title="deno.json"
{
"compilerOptions": {
"jsx": "react-jsx",
- "jsxImportSource": "react"
+ "jsxImportSource": "preact"
},
"imports": {
- "react": "npm:react"
+ "preact": "npm:preact"
}
}
```
### 开发转换
将 `"jsx"` 选项设置为 `"react-jsxdev"` 而不是 `"react-jsx"` 将为每个 JSX 节点传递额外的调试信息。额外的信息包括每个 JSX 节点调用位置的文件路径、行号和列号。
这些信息通常在框架中用于增强开发期间的调试体验。在 React 中,这些信息用于增强堆栈跟踪,并显示组件在哪个位置被实例化,通常在 React 开发者工具浏览器扩展中显示。
使用 `"react-jsxdev"` 选项将 JSX 转换为以下 JavaScript 代码:
```jsx
// 输入
const jsx = (
);
// 输出
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
const _jsxFileName = "file:///input.tsx";
const jsx = _jsxDEV(
"div",
{
className: "foo",
children: _jsxDEV(
MyComponent,
{
value: 2,
},
void 0,
false,
{
fileName: _jsxFileName,
lineNumber: 3,
columnNumber: 5,
},
this,
),
},
void 0,
false,
{
fileName: _jsxFileName,
lineNumber: 1,
columnNumber: 14,
},
this,
);
```
:::caution
仅在开发期间使用 `"react-jsxdev"`,不要在生产环境中使用。
:::
### 使用 JSX 导入源谕语
无论您是否为项目配置了 JSX 导入源,还是使用默认的“旧版”配置,您都可以向 `.jsx` 或 `.tsx` 模块添加 JSX 导入源谕语,并且 Deno 会尊重它。
`@jsxImportSource` 谕语需要位于模块的开头注释中。例如,要使用来自 esm.sh 的 Preact,您可以这样做:
```jsx
/** @jsxImportSource https://esm.sh/preact */
export function App() {
return (
Hello, world!
);
}
```
### `jsxImportSourceTypes`
在某些情况下,库可能不提供类型。要指定类型,您可以使用 `@jsxImportSourceTypes` 谕语:
```jsx
/** @jsxImportSource npm:react@^18.3 */
/** @jsxImportSourceTypes npm:@types/react@^18.3 */
export function Hello() {
return Hello!
;
}
```
或者通过 _deno.json_ 中的 `jsxImportSourceTypes` 编译器选项进行指定:
```json title="deno.json"
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "npm:react@^18.3",
"jsxImportSourceTypes": "npm:@types/react@^18.3"
}
}
```
## JSX 预编译转换
Deno 附带了一种 [新 JSX 转换](https://deno.com/blog/v1.38#fastest-jsx-transform),其针对服务器端渲染进行了优化。与其他 JSX 转换选项相比,它可能快 **7-20 倍**。区别在于,预编译转换静态分析您的 JSX,并在可能的情况下存储预编译的 HTML 字符串。这可以避免在创建 JSX 对象时消耗大量时间。
要使用预编译转换,请将 `jsx` 选项设置为 `"precompile"`。
```diff title="deno.json"
{
"compilerOptions": {
+ "jsx": "precompile",
"jsxImportSource": "preact"
},
"imports": {
"preact": "npm:preact"
}
}
```
为了防止代表 HTML 元素的 JSX 节点被预编译,您可以将它们添加到 `jsxPrecompileSkipElements` 设置中。
```diff title="deno.json"
{
"compilerOptions": {
"jsx": "precompile",
"jsxImportSource": "preact",
+ "jsxPrecompileSkipElements": ["a", "link"]
},
"imports": {
"preact": "npm:preact"
}
}
```
:::note
`precompile` 转换与 [Preact](https://preactjs.com/) 或 [Hono](https://hono.dev/) 最为兼容。它在 React 中不支持。
:::
使用 `"precompile"` 选项将 JSX 转换为以下 JavaScript 代码:
```jsx
// 输入
const jsx = (
);
// 输出:
import {
jsx as _jsx,
jsxTemplate as _jsxTemplate,
} from "npm:preact/jsx-runtime";
const $$_tpl_1 = [
'',
"
",
];
function MyComponent() {
return null;
}
const jsx = _jsxTemplate(
$$_tpl_1,
_jsx(MyComponent, {
value: 2,
}),
);
```
## 在服务器响应中渲染 JSX
在 Deno 中使用 JSX 进行服务器端渲染时,您需要将 JSX 组件转换为可以在响应中发送的 HTML 字符串。这在使用 Deno.serve 构建 Web 应用程序时特别有用。
### 使用 Preact 和 renderToString
对于 Preact 应用程序,您可以使用 `preact-render-to-string` 包:
```json title="deno.json"
{
"compilerOptions": {
"jsx": "precompile",
"jsxImportSource": "preact"
},
"imports": {
"preact": "npm:preact@^10.26.6",
"preact-render-to-string": "npm:preact-render-to-string@^6.5.13"
}
}
```
然后在你的服务器代码中:
```tsx title="server.tsx"
import { renderToString } from "preact-render-to-string";
const App = () => {
return Hello world
;
};
Deno.serve(() => {
const html = `${renderToString()}`;
return new Response(html, {
headers: { "Content-Type": "text/html; charset=utf-8" },
});
});
```
这种方法与预编译转换配合良好,提供了最佳的服务器端渲染性能。
### 使用 React 的 renderToString
如果你使用 React 而不是 Preact,可以使用 React 自身的服务器渲染能力:
```json title="deno.json"
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
},
"imports": {
"react": "npm:react@^18.2.0",
"react-dom": "npm:react-dom@^18.2.0",
"react-dom/server": "npm:react-dom@^18.2.0/server"
}
}
```
在您的服务器代码中:
```tsx title="server.tsx"
import { renderToString } from "react-dom/server";
const App = () => {
return Hello from React
;
};
Deno.serve(() => {
const html = `${renderToString()}`;
return new Response(html, {
headers: { "Content-Type": "text/html; charset=utf-8" },
});
});
```
使用这些配置,您的 Deno 服务器可以高效地将 JSX 组件渲染为 HTML 并将其提供给客户端。