React编译报错:Unexpected token < 求助——跨项目组件引入场景下JSX编译失败
这个错误的核心原因很明确:你的App A没有对安装在node_modules里的App B(即connector_frontend)代码进行JSX转译。
React的JSX语法并不是原生JavaScript支持的语法,必须通过Babel这类工具转译成React.createElement调用才能被浏览器/构建工具识别。而绝大多数React项目的构建配置(比如Webpack+Babel)默认都会跳过node_modules目录下的代码转译——因为通常来说,npm包发布的都是已经转译好的产物,不需要再处理。但你现在直接引用的是App B的源码(未转译的JSX),所以App A的构建工具看到<p>标签时,会把它当作无效的JavaScript语法,抛出Unexpected token错误。
而你返回纯文本时编译成功,是因为纯字符串是原生JavaScript支持的语法,不需要额外转译。
下面是两种可行的解决方案:
方案1:让App B发布编译后的产物(推荐)
这是npm包的标准做法,你需要在App B中配置构建流程,把源码转译成可直接使用的JavaScript代码,然后在App B的package.json中指定正确的入口文件:
- 在App B中添加Babel/Webpack配置,将源码编译到
dist目录(或其他指定目录)。 - 修改App B的
package.json,把main字段指向编译后的文件,比如:{ "main": "dist/index.js" } - 当你在App A中安装App B后,直接引用包名即可,不需要写源码路径:
import ConnectorFormView from "connector_frontend";
这样App A引用的就是已经转译好的代码,自然能识别JSX转译后的语法。
方案2:修改App A的配置,强制转译App B的代码
如果暂时不想给App B做打包,可以修改App A的构建配置,让它对node_modules/connector_frontend目录下的代码进行转译:
针对Webpack+Babel的配置示例:
在App A的Webpack配置文件中,调整babel-loader的排除规则,把connector_frontend排除在忽略列表之外:
module.exports = { // ...其他配置 module: { rules: [ { test: /\.(js|jsx)$/, // 排除node_modules,但例外处理connector_frontend exclude: /node_modules(?!\/connector_frontend)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'] } } } ] } };
针对Babel单独配置的示例:
在App A的babel.config.js或.babelrc中,调整忽略规则:
{ "presets": ["@babel/preset-react", "@babel/preset-env"], "ignore": [ "node_modules/**", // 取消对connector_frontend目录的忽略 "!node_modules/connector_frontend/**" ] }
修改后,App A的构建工具会对App B的源码进行转译,JSX语法就能被正确识别了。
内容的提问来源于stack exchange,提问作者Lukas Hanincik

