在学习配置 JSX 使用自定义函数编译时遇到如下报错。

[vite] Internal server error: /demo/react-mini-demo/src/main.tsx: pragma and pragmaFrag cannot be set when runtime is automatic.
> 1 | // import React from 'react';
    | ^
  2 | import ReactDOM from 'react-dom';
  3 | import './index.css';
  4 |
  Plugin: vite:react-babel
  File: /demo/react-mini-demo/src/main.tsx
      at File.buildCodeFrameError 
……

我尝试使用的是通过注释方式 /** @jsx BinReact.createElement */ 配置,代码如下

function createElement(type: string, props: any, ...children: Array<object | string>) {
	return {
		type,
		props: {
			...props,
			children,
		},
	};
}

const BinReact = {
	createElement,
};

/** @jsx BinReact.createElement */
const element = (
	<div id="foo">
		<a>bar</a>
		<b />
	</div>
);

在编译的时候就出现了开头的错误提示我说自动运行时环境不能配置 pragma 和 pragmaFrag。

刚开始我并不理解这段报错的意思,于是通过不断查找我找到一个老哥提到了将 jsxRuntime 配置为 classic

相关 issues : https://github.com/emotion-js/emotion/issues/2041#issuecomment-719819128

通过增加 /** @jsxRuntime classic */ 确实是解决了问题,代码如下

……

/** @jsxRuntime classic */
/** @jsx BinReact.createElement */
const element = (
	<div id="foo">
		<a>bar</a>
		<b />
	</div>
);

到这里就结束了嘛?不,问题是解决了。但是原因是啥呢?

其实在找到这个链接之前我就大胆猜测是 babel 的问题,确实也在翻 babel 的文档,不过最终还是一头雾水。不过现在我们找到答案了,再通过解决方案反推一下是不是就能找到相关的文档呢,这样也有助于好好了解一下 React JSX 编译的这些配置。

首先我们看看编译 JSX 是用的啥工具,我这里其实能看的出来用的是 vite 然后编译 React 的工具通过 package.json 文件就能看到,这个依赖列表就非常清楚哈,除了 vite 本体和 react 以及 react-dom 之外还有一个 @vitejs/plugin-react

解决 @babel/plugin-transform-react-jsx 自动运行时环境不能配置 pragma 和 pragmaFrag 问题-天真的小窝

那到 node_modules 下面看看 @vitejs/plugin-react 有些啥。

解决 @babel/plugin-transform-react-jsx 自动运行时环境不能配置 pragma 和 pragmaFrag 问题-天真的小窝

这不就找到关键点了嘛,就是 @babel/plugin-transform-react-jsx 通过对它的一通搜索,我找的一篇 React 官网的文章《介绍全新的 JSX 转换》 https://zh-hans.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html 就是在介绍这个玩意(? 是不是暴露了我不认真看 React 文档… 果然出来混迟早要还的)。通过对这篇文档阅读,我们发现 @babel/plugin-transform-react-jsx 是 React 团队和 babel 团队合作新推出的一个全新版本的 JSX 编译工具,文章中对于新的 @babel/plugin-transform-react-jsx 和旧的 @babel/preset-react 工具之间的区别做了详细的介绍和说明,我这里就不详细赘述了。当然我这篇博客呢关注点主要是在怎么配置 @babel/plugin-transform-react-jsx 解决我们的报错,文章中将我带到了 Babel 文档中的 @babel/plugin-transform-react-jsx 这不就找到了嘛。

关于 @jsxRuntime 是有两个参数的分别是 automatic 自动模式(默认)和 classic 传统模式

为啥 automatic 模式是不能配置 @jsx 参数的呢?其实如果你看了上面的《介绍全新的 JSX 转换》 这篇文章就能自己找到答案了。

如果你问我在找到解决方案之后还花时间去看后面这些东西的意义是啥的话,我想说重点不是我解决问题的结果,而是我找到了解决问题的过程…

好了,今天的博客就先写到这里,鸽了个把月没写博客了(? 其实不是我想鸽,是现在感觉如果只是像之前一样水一篇的话感觉还不如不写…)。