详解 TypeScript 编译 TSX 文件

一、简介

因为使用 Cycle.js 的 Vite + TSX 所以想详细的探索 TSX 在 TS 配置中的编译情况,本文主要讲解 tsconfig 和 tsx 编译与配置。以常见的框架 PReact 的虚拟 DOM + TSX 组合、snabbdom + TSX 组合不同的配置以及编译输出。

除了 TS 还可以渲染, babel 等编译器进行编译。

二、配置项目

配置选项 描述 示例配置
"jsx" 指定 JSX 的处理方式 "jsx": "react"
"jsxFactory" 指定在 JSX 中使用的工厂函数 "jsxFactory": "h"
"jsxFragmentFactory" 指定在 JSX 中使用的碎片工厂函数 "jsxFragmentFactory": "Fragment"
"jsxImportSource" 指定从哪个模块导入 JSX 相关的符号 "jsxImportSource": "react"
"reactNamespace" 指定全局变量或模块的命名空间,用于 React "reactNamespace": "myReact"
"jsxMode" 指定 JSX 模式,仅在 TypeScript 4.1+ 中可用 "jsxMode": "react"

例如: Preact 提供了自己的渲染函数 h, 用来渲染组件,此时就对应着 jsxFactory 配置项。

三、配置文件和命令行的优先级问题

  • 命令行参数优先级
  • 配置文件优先级

例如: jsx 标识符在命令行中使用 --jsx react 会覆盖 jsx: react-jsx

四、JSX 标识

1) 没有标识符

没有标识符时候,不支持编译 TSX/JSX 文件。

2)preserve 标识符

默认会将 TSX 文件装换成 JSX 文件, 其他的 JSX 结构没有改变

3)react/react-native 标识符

默认会使用 React.createElement 来创建元素,输出 js 文件,可以与 jsxFactory 工厂函数替换库中的函数

4)react-jsx/react-jsxdev

会使用相关 React 的 jsx-runtime 进行编译,也可以使用自定义 jsx-runtime 运行时。

五、PReact 虚拟dom 和 JSX

1) 写法一: 使用 preact 运行时

json 复制代码
{
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
}

得到的编译结果是:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("preact/jsx-runtime");
function Card({ title, children }) {
    return ((0, jsx_runtime_1.jsxs)("div", { class: "card", children: [(0, jsx_runtime_1.jsx)("h1", { children: title }), children] }));
}

使用 preact 的 jsx 运行时。

2) 写法二: 使用 preact 提供的渲染函数 h 进行渲染

json 复制代码
{
    "jsx": "react",
    "jsxFactory": "h",  
}

得到的编译结果是:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const preact_1 = require("preact");
function Card({ title, children }) {
    return ((0, preact_1.h)("div", { class: "card" },
        (0, preact_1.h)("h1", null, title),
        children));
}
;

使用 preact 的渲染函数 h。

六、snabbdom 与 @herp-inc/snabbdom-jsx

1)写法一:使用 jsx

ts 复制代码
{
    "jsx": "react-jsx",
    "jsxImportSource": "@herp-inc/snabbdom-jsx",
}

编译结果

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("@herp-inc/snabbdom-jsx/jsx-runtime");
// import { jsx } from '@herp-inc/snabbdom-jsx'
const EventComp = () => {
    return (0, jsx_runtime_1.jsx)("div", { children: "sdfdsfdd" });
};
exports.default = EventComp;

使用 jsx 的运行时

2) 写法: jsx 使用

ts 复制代码
{
    "jsx": "react", 
    "jsxFactory": "jsx",
    "jsxFragmentFactory": "Fragment", 
}

编译的结果:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const snabbdom_jsx_1 = require("@herp-inc/snabbdom-jsx");
const EventComp = () => {
    return (0, snabbdom_jsx_1.jsx)("div", null, "sdfdsfdd");
};
exports.default = EventComp;

使用@herp-inc/snabbdom-jsx内部实现的 jsx 函数。

七、snabbdom-jsx

没有运行时:snabbdom-jsx/jsx-runtime 所以不能使用 jsx 运行时编译

1)写法一

ts 复制代码
{
    "jsx": "react", 
    "jsxFactory": "html", 
}

组件写法以及编译后的写法

ts 复制代码
import { html } from 'snabbdom-jsx';

export const vnode = <div>Hello JSX</div>


"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.vnode = void 0;
const snabbdom_jsx_1 = require("snabbdom-jsx");
exports.vnode = (0, snabbdom_jsx_1.html)("div", null, "Hello JSX");

本质是使用了 snabbdom-jsx 提供的 html函数,源码如下:

ts 复制代码
module.exports = {
  html: JSX(undefined),
  svg: JSX(SVGNS, 'attrs'),
  JSX: JSX
};

小结

本文的主要目的是讲解 TS 中编译配置和在不同的环境下编译不同的 JSX/TSX 文件,由于 React 的JSX 实现了 jsx-runtime,所以基本上都有两套编译路径。若不了解 TSX 编译,本文可以很好的说明。其次可以使用 babel 等其他的工具进行编译学习。Cycle.js 中使用 snabbdom 作为虚拟 dom, 可以使用 TSX 不优雅的虚拟 dom 的写法。

相关推荐
天平17 小时前
油猴脚本创建webworker踩坑记录
前端·javascript·typescript
原则猫19 小时前
前端基础大厦
前端
陈随易20 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart21 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒1 天前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰1 天前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
竹林8181 天前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
用户8356290780511 天前
Python 实现 PDF 文件加密与解密方法
后端·python
小满zs1 天前
Go语言第二章(小无相功)
后端·go
用户8356290780511 天前
使用 Python 冻结与拆分 Excel 窗格教程
后端·python