Monorepo中React Native导入共享React组件无法解析@babel/runtime模块
问题根因
该报错是Monorepo架构下React Native的Metro打包器的模块解析规则和Babel转译范围限制导致的:
- Metro默认只会解析当前项目(mobile目录)内的依赖,不会主动到根目录node_modules或上层共享目录查找依赖
- Babel默认不会转译当前项目目录外的代码,上层modules目录下的React组件没有被正确转译,导致依赖@babel/runtime的运行时辅助函数找不到
- @babel/runtime被放在devDependencies中,运行时无法正常加载
解决方案
步骤1:修正metro.config.js配置
修改mobile目录下的metro.config.js,明确添加共享目录和根目录依赖的解析规则:
const path = require('path'); const projectRoot = __dirname; const workspaceRoot = path.resolve(projectRoot, '../..'); module.exports = { watchFolders: [ // 监听共享模块目录 path.resolve(workspaceRoot, 'modules'), // 监听根目录node_modules path.resolve(workspaceRoot, 'node_modules'), ], resolver: { nodeModulesPaths: [ // 优先查找mobile本地的node_modules path.resolve(projectRoot, 'node_modules'), // 其次查找根目录的node_modules path.resolve(workspaceRoot, 'node_modules'), ], extraNodeModules: { // 锁定公共依赖的路径,避免多版本冲突 'react': path.resolve(projectRoot, 'node_modules/react'), 'react-native': path.resolve(projectRoot, 'node_modules/react-native'), '@babel/runtime': path.resolve(projectRoot, 'node_modules/@babel/runtime'), }, }, transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, };
步骤2:扩展Babel转译范围
在mobile目录下新建/修改babel.config.js,把上层共享模块目录加入转译白名单:
module.exports = { presets: ['module:metro-react-native-babel-preset'], babelrcRoots: [ '.', // 转译所有modules下的模块 '../../modules/*', ], };
步骤3:修正@babel/runtime的依赖类型
@babel/runtime是运行时必需依赖,需要从devDependencies移动到dependencies:yarn add @babel/runtime
或者npm install @babel/runtime --save
步骤4:清除缓存重启服务
避免旧缓存影响,按顺序执行清理命令:
- 停止当前运行的Metro服务
- 执行
watchman watch-del-all - 执行
rm -rf node_modules && yarn install - 执行
rm -rf /tmp/metro-* - 启动服务时加上重置缓存参数:
yarn start --reset-cache
可选步骤:调整根目录nohoist配置
如果你的mobile是Expo项目,需要确保根目录package.json中的nohoist配置覆盖到mobile目录,避免依赖被提升后解析失败:
"nohoist": ["**/mobile/**", "**/expoapp/**"]
内容的提问来源于stack exchange,提问作者Jim B.
相关产品推荐
相关产品推荐

