如何解决Monorepo React项目中「缺少额外Loader」的报错?
React Monorepo 共享组件编译报错解决方案
问题根源
报错提示Module parse failed: Unexpected token,本质是主应用的Webpack未对共享包的TSX/JSX代码进行转译。默认情况下,React项目(无论是CRA还是自定义Webpack)只会处理当前项目src目录内的文件,共享包的源码不在这个范围内,导致JSX语法无法被Babel解析。
解决方法
方案一:修改Webpack配置,让主应用转译共享包源码
如果你的子应用是用Create React App(CRA)创建的,直接修改Webpack配置需要借助craco或react-app-rewired,步骤如下:
- 安装依赖:
npm install @craco/craco --save-dev
- 在子项目根目录创建
craco.config.js,添加配置:
const path = require('path'); module.exports = { webpack: { configure: (webpackConfig) => { // 找到处理JSX/TSX的规则,把共享包目录加入include列表 webpackConfig.module.rules[1].oneOf.forEach(rule => { if (rule.test?.toString().includes('jsx|tsx')) { rule.include.push(path.resolve(__dirname, '../shared')); } }); return webpackConfig; } } };
- 修改子项目
package.json的启动脚本:
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" }
如果是自定义Webpack配置的项目,直接修改webpack.config.js:
const path = require('path'); module.exports = { // ...其他配置 module: { rules: [ { test: /\.(tsx|ts|jsx|js)$/, include: [ path.resolve(__dirname, 'src'), path.resolve(__dirname, '../shared') // 加入共享包路径 ], use: 'babel-loader', exclude: /node_modules/ } ] } };
方案二:将共享包编译为产物后再引入
如果不想修改主应用配置,可以把共享包先编译成可直接使用的代码:
- 在共享包的
package.json中配置入口与编译脚本:
"main": "dist/index.js", "scripts": { "build": "babel src --out-dir dist --extensions .tsx,.ts,.jsx,.js" }
- 安装Babel依赖:
npm install @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript --save-dev
- 创建共享包的
.babelrc配置:
{ "presets": [ "@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript" ] }
- 修改主应用的引入路径,直接引用包名即可:
// 之前的写法 // import TEST from "@teamcenter-extension-monorepo/shared/src/components/TEST"; // 修改后 import TEST from "@teamcenter-extension-monorepo/shared";
- 每次修改共享包后,先执行
npm run build再启动主应用。
额外注意事项
- 若使用TypeScript,需在主应用的
tsconfig.json中添加路径映射:
{ "compilerOptions": { // ...其他配置 "paths": { "@teamcenter-extension-monorepo/shared/*": ["../shared/src/*"] } } }
内容的提问来源于stack exchange,提问作者MWB
相关产品推荐
相关产品推荐

