Expo SDK45 React Native安卓生产包图片不显示问题咨询
Expo SDK 45 安卓生产构建本地图片不显示问题解决方案
问题表现
- 安卓production build(生产构建)环境下部分本地静态图片无法正常渲染,Expo dev-client开发环境下相同图片加载正常
- 同套代码降级到Expo SDK 44及更低版本时,所有图片加载逻辑无异常
- 问题关联实现代码:
<TouchableOpacity style={{ position: "absolute", right: 30, top: 20 }} onPress={() => this.setState({ displayInfo: !this.state.displayInfo })}> <Image source={require('./../../../../assets/icona_info.png')} resizeMode="contain" style={{ width: 36, height: 36 }} /> </TouchableOpacity>
根因定位
该问题是Expo SDK 45内置Metro打包器的已知bug:
- 开发环境下Metro直接从源文件路径实时读取资源,不会触发生产构建阶段的资源压缩、hash重命名、目录扁平化流程,因此dev-client下资源可以正常加载
- 生产构建时,Metro会把所有静态资源统一打包到安卓包的根assets目录下,当代码中使用超过3层
../的相对路径引用资源时,打包器的路径计算逻辑会出错,导致资源映射ID和实际打包进APK的资源路径不匹配,最终图片加载失败 - 低版本SDK的Metro没有做资源目录扁平化处理,因此不存在该路径计算问题
修复方案
按优先级选择以下方案即可解决问题:
- 优先方案:替换多层相对路径引用为根路径/别名引用
避免写多层../的相对路径,直接使用项目根路径引用资源,比如根目录下的assets文件夹内的图片,直接写require('/assets/icona_info.png');也可以通过babel-plugin-module-resolver配置路径别名,将@assets指向项目根目录的assets文件夹,使用require('@assets/icona_info.png')的写法,彻底规避相对路径计算错误。 - 备选方案:修改Metro配置绕过bug
在项目根目录的metro.config.js中添加如下配置,修正资源路径解析逻辑:
const { getDefaultConfig } = require('expo/metro-config'); const defaultConfig = getDefaultConfig(__dirname); // 修复SDK45多层相对路径资源打包映射错误 defaultConfig.transformer = { ...defaultConfig.transformer, assetPlugins: [], }; module.exports = defaultConfig;
配置修改完成后,执行expo start -c清除Metro打包缓存,再执行expo prebuild --clean清除原生构建缓存,重新打生产包即可。
- 临时规避方案:缩短资源引用层级
把加载异常的图片移动到引用组件的相邻目录,将相对路径的../层级控制在2层以内,也可以绕过该打包bug,适合快速验证修复的场景。
注意:修复完成后必须清除所有构建缓存再重新打包,否则旧的错误资源映射缓存会残留,导致问题复现。
内容的提问来源于stack exchange,提问作者red
相关产品推荐
相关产品推荐

