如何在Expo/React Native项目的EAS Build中使本地共享TypeScript包可被正确解析?
如何在Expo/React Native项目的EAS Build中使本地共享TypeScript包可被正确解析?
嘿,我之前在monorepo里用本地TypeScript包配合EAS Build的时候,也踩过几乎一模一样的坑!本地跑起来顺得不行,一到远程构建就报模块找不到,折腾了好一阵才摸清楚门道,给你几个实用的解决办法:
先排查最基础的匹配问题
先看看你是不是犯了我一开始的低级错误:包名和导入路径完全不匹配。
从你的描述来看,你的shared包的package.json里name是@shared/types,但报错里的代码是从@myProjectName/shared导入的——这俩名字完全对不上,EAS肯定找不到啊!先把导入语句里的包名改成和shared包package.json里的name完全一致,比如包名是@shared/types,那导入就得写成import { ... } from "@shared/types",同时mobile-app的package.json里的依赖也要对应上,别再搞混了。
方案1:修复手动复制包的构建配置(适合临时场景)
你现在是手动把shared包复制到mobile-app里的shared_local目录,用file:路径引入,那得确保EAS在远程构建时能正确处理这个目录:
- 先在本地编译shared包:进入shared目录,执行
tsc命令,把TypeScript代码编译成JS文件和类型声明(要确保你的shared包的tsconfig.json里配置了outDir比如dist,还有declaration: true,这样才能生成类型文件) - 完整复制shared包内容到shared_local:把shared目录下的package.json、dist目录(还有src目录如果需要的话)完整复制到mobile-app/shared_local里,别漏了package.json——EAS全靠它识别这个包的信息
- 核对依赖配置:检查mobile-app/package.json里的依赖项,确保是
"@shared/types": "file:./shared_local",和shared_local/package.json里的name完全一致 - 本地验证后再提交:在mobile-app目录里执行
npm install或者yarn install,确保本地能正常解析这个包,然后把shared_local目录和所有配置文件一起提交到代码仓库,EAS构建时就会自动处理这个file类型的依赖了
方案2:用monorepo工作区管理(更长期的优雅方案)
手动复制包太麻烦了,还容易出现代码不同步的问题,推荐用npm/yarn的工作区来统一管理你的monorepo:
- 根目录配置工作区:在my-app根目录创建一个package.json,内容如下:
{ "private": true, "workspaces": [ "shared", "mobile-app", "cloud-functions" ] }
- 修改mobile-app的依赖配置:把mobile-app/package.json里的共享包依赖改成工作区引用,比如
"@shared/types": "workspace:../shared" - 给EAS开启工作区支持:打开mobile-app/eas.json,给每个构建profile(比如production、development)加上npm客户端和工作区配置:
{ "build": { "production": { "npmClient": "yarn", // 用npm的话就改成"npm" "workspaces": true }, "development": { "npmClient": "yarn", "workspaces": true } } }
- 本地安装依赖后提交:在my-app根目录执行
yarn install或者npm install,让所有工作区的依赖正确关联,然后把所有配置文件提交到仓库,EAS构建时就会自动识别并拉取工作区里的共享包了
方案3:额外配置TypeScript路径别名(解决类型解析问题)
如果已经解决了模块解析的问题,但还是出现类型找不到的报错,可以在mobile-app里配置路径别名:
- 修改tsconfig.json:在compilerOptions里加上路径配置:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@shared/types": ["./shared_local/src"] // 用工作区的话就写成["../shared/src"] } } }
- 配置Metro打包器:在mobile-app的metro.config.js里添加别名配置,让Metro也能识别这个路径:
const { getDefaultConfig } = require('expo/metro-config'); const path = require('path'); const config = getDefaultConfig(__dirname); config.resolver.alias = { ...config.resolver.alias, '@shared/types': path.resolve(__dirname, './shared_local/src'), }; module.exports = config;
这样不管是TypeScript编译还是Metro打包,都能正确找到类型文件了
额外要注意的小细节
- 别把node_modules目录提交到仓库,EAS构建时会自动安装所有依赖
- 确保shared包的TypeScript配置是正确的,一定要生成类型声明文件,不然React Native项目可能会找不到类型
- 如果用pnpm的话,要在eas.json里额外配置
pnpmWorkspace: true,不过npm和yarn的配置更简单
内容来源于stack exchange
相关产品推荐
相关产品推荐

