reactjs - 什么不能从 NPM 包中导出 JSX
问题描述
我正在编写一个库,将一些 React 组件作为其 API 的一部分公开。
我将在这里做一些假设:
1 - 它将在反应项目中使用。
2 - 这些项目将在某个时候捆绑它们的依赖项。
3 - 那些 react 项目可以使用 JSX 作为描述 UI 的一种方式。
4 - 他们选择的打包工具,Webpack 如果它是一个 create-react-app,将使用 babel 来解析 JSX 并将其转译成 vanilla JS。
按照这个逻辑,我应该能够从外部包中导出一些 JSX,因为包的代码将与应用程序一起捆绑、转译。
但是,当我在 create-react-app 项目中这样做时,我收到以下错误:
SyntaxError:/Users/someone/Desktop/someproject/dist/esm/index.js:当前未启用对实验语法“jsx”的支持 (35:13):
将 @babel/preset-react ( https://git.io/JfeDR ) 添加到 Babel 配置的“预设”部分以启用转换。如果您想保持原样,请将 @babel/plugin-syntax-jsx ( https://git.io/vb4yA ) 添加到“插件”部分以启用解析。
是的,我可以转换 JSX,也许我会。我只是看不出有任何理由,如果它无论如何都会被捆绑。我更喜欢将转译调整和优化留给用户。
我担心的是,如果我自己编译它,我有两个选择。
在范围内导入 React,并使用 babel 转
<MyComponent/>
成React.createElement()
,但这将排除使用新 JSX 转换的可能性
我自己使用新的 JSX 转换,并确定我的代码是否与 17 之前的 React 版本兼容。并增加我自己的包大小,因为 babel 添加了很多代码来实现这一点。
在这一点上,我认为我对这个问题感到非常兴奋,因为坦率地说,我不知道为什么我不能从我的包中导出纯 JSX。我知道我可能遗漏了一些明显的东西,比如分号或其他什么,但我真的很想了解。
如果你想要一些代码/汇总 - babel configs 随时询问。
坦克!
解决方案
乍一看,您的逻辑似乎很有意义。但是让我们看看为什么这是一个坏主意。
JSX 是一种特殊的语法,必须将其转换为浏览器或Nodejs可以理解的最低通用恶魔。这就是捆绑器所做的,正如您所提到的,任何在节点环境中使用 react 的人几乎肯定会使用捆绑器来执行此操作。
但是,人们可能会在他们的代码中使用许多奇怪的语法。当捆绑器从 node_module 导入代码时,如果这些模块中的代码尚未转译,则捆绑器也需要转译它们。考虑到未转译的模块可能有许多奇怪的语法,每个模块都需要自己的转译指令(想想 babel 配置)。为每个 node_module 拥有唯一的转译配置将非常笨拙,更不用说必须转译每个 node_module,可能以不同的方式,对性能不利。
解决这个问题的普遍接受的最佳实践是简单地使用一个bunder来构建你的包,它将代码归结为最低的公分母。这使您的包用户的捆绑器能够“按原样”引入 node_module 中的代码。
虽然可能会想出一些疯狂的 babe/webpack/rollup 指令来将您的模块自定义解释为 JSX,但您真的希望您的库用户必须这样做吗?尤其是在使用 create-react-app 的人的情况下,本机不支持自定义 CRA 的 babel 配置,这意味着他们需要采取额外的步骤才能使您的库正常工作。此外,出于明显的性能原因,webpack 默认将 node_modules 从 js 转换中排除,CRA 遵循此约定。发布库时,您希望它们尽可能易于使用且普遍可用。
编译、调整和优化代码最好留给编写代码的人,在您尝试发布的 React 组件库的情况下,就是您自己。
推荐阅读
- azure-devops - Azure DevOps 查询 - 显示我昨天参与的所有工作项
- php - 运行 php artisan 备份时出错:运行
- html - 在 qt 中使用 WTemplate 创建弹出菜单
- channel - 是否有任何用于 Houzz 集成的 api 参考或文档?
- assembly - 如果在程序执行时更改 GDT 会发生什么?
- java - Spring Boot Rest Web Service在获取请求中获取多个参数
- git - 如何创建一个 git 存储库以在每次推送到原始存储库时获取另一个存储库?
- python - AttributeError: ("'str' 对象没有属性 'str'", '发生在索引 31978')
- javascript - Sequelize 在关联上添加类型转换
- coldfusion - this.smtpServersettings 将邮件发送到未投递的选项而不是 gmail