React Native应用如何实现远程bundle加载的可安装功能模块
React Native 动态拉取远程Bundle实现按需加载方案
核心诉求
- 支持应用从远程服务器拉取、下载、加载存储在远端的Bundle包,实现功能按需下发
需求背景
- 计划开发初始版本仅内置最小必要功能的React Native应用,用户需要使用额外功能时,可直接在应用内的安装菜单选择对应功能触发下载,对应功能的代码/SDK从远程服务器拉取,下载完成后用户无需重装应用即可直接使用该功能
参考落地场景
- 计算器类应用:默认仅内置加法、减法基础计算功能,乘法、除法作为可选扩展功能提供;用户点击安装对应功能后,应用下载对应代码包,加载完成即可使用乘除计算能力
- 游戏类应用:实现类似《使命召唤》《PUBG》的游戏内动态下载逻辑,支持按需下载地图、角色资源等扩展内容,不全量打包到初始安装包中
硬性验收要求
- 初始发布的ipa、apk安装包内,不得通过条件语句预置、打包任何扩展功能的相关代码
- 全链路实现不得使用Web View承载扩展功能
具体实现思路
1. 底层能力选型
核心原则:所有扩展功能与主包做编译时完全隔离,从构建根源避免扩展代码被误打进初始安装包
- 直接采用React Native官方原生提供的动态Bundle加载能力:安卓端通过
ReactInstanceManager提供的多Bundle加载接口实现,iOS端通过RCTBridge的动态Bundle挂载逻辑实现,整个渲染链路全为RN原生组件,完全不需要依赖WebView - 初始主包仅保留4类核心模块:基础导航框架、扩展功能列表展示页、下载管理模块、Bundle加载调度模块;所有扩展业务代码完全不加入主工程的编译依赖,从构建层面杜绝扩展代码进入初始安装包的可能
2. 扩展Bundle打包规范
- 每个扩展功能单独配置Metro打包入口,打包时自定义
createModuleIdFactory方法,给每个扩展包内的模块分配全局唯一ID,避免和主包、其他扩展包的模块ID冲突导致加载报错 - 开启Metro的
experimentalImportBundleSupport配置做Bundle拆分:将所有扩展共用的RN基础运行时、公共组件抽到公共基础Bundle中,该公共Bundle属于运行时基础依赖,不属于扩展功能代码,可放在主包内;每个扩展功能单独打为可独立加载的业务Bundle,互不干扰 - 每个Bundle打包完成后计算对应MD5校验值,和Bundle版本号、兼容的最低主应用版本号、下载地址一起存储在服务端,供端侧拉取做校验
3. 端侧落地流程
- 应用启动后调用服务端接口拉取全量可安装的扩展功能列表,在应用内安装菜单展示每个功能的名称、占用大小、版本说明
- 用户点击安装对应功能时,端侧启动断点续传下载任务,将Bundle文件下载到应用私有沙盒的专属目录;下载完成后先校验本地文件MD5与服务端返回值是否一致,校验通过再标记为已安装,避免损坏文件导致加载崩溃
- 用户点击打开已安装的扩展功能时,端侧直接调用RN原生接口加载沙盒内对应路径的业务Bundle,加载完成后直接渲染对应页面,全程走RN原生渲染链路,无WebView参与
4. 避坑提示
- iOS端提审注意:动态加载的内容仅限RN层的业务功能,不要用该机制修改原生层逻辑、不要替换应用核心功能,避免触发App Store审核规则被拒
- 主包代码内不要写任何和具体扩展功能绑定的条件判断、代码引用,扩展功能的路由注册、入口挂载逻辑全部写在扩展Bundle内部:Bundle加载完成后自动向主包的路由表注册自身入口,主包不需要提前感知扩展功能的具体实现
- 加载扩展Bundle前必须做版本兼容校验,如果当前主应用版本低于扩展Bundle要求的最低版本,直接提示用户升级主应用,不要强行加载导致崩溃
内容的提问来源于stack exchange,提问作者Avinash
相关产品推荐
相关产品推荐

