了解Vega应用程序的系统套件
基于React Native构建的现代应用程序通常会附带大型的单体JavaScript包。这些捆绑包中包含所有内容,从核心React库到应用程序特定的业务逻辑。不过,这种方法也带来了挑战:应用程序更大,启动更慢,交付错误修复时“摩擦力”也更大。
Vega引入了拆分包系统,在该系统中,常用库位于系统上,应用程序则仅提供其独有的代码。本文探讨了这意味着什么、它为何重要以及它的工作原理。
关于拆分包
传统上,React Native应用程序会发布一个包含以下内容的应用程序包:
- 像
react和react-native这样的核心库 - Vega专属模块
- 第三方库
- 您应用程序的代码
使用拆分包时,应用程序包将会分为两部分:
系统(常用)包
该包预安装在设备上,它包含广泛使用的库,例如react、react-native和@amazon-devices/react-native-kepler。有关详细信息请参阅系统分发库。系统包与原生Vega运行时保持同步。
拆分应用程序包
您的应用程序包减去常用库。其中仅包含应用程序专属代码和任何专属依赖项。
如何转化
以下是如何拆分单体包的简化示意图:
┌────────────────────────────┐
│ 单体应用程序包 │
│(React、RN、Vega、应用程序)│
└────────────────────────────┘
│
▼
┌────────────────────┐ ┌─────────────────────┐
│ 系统包 │ │ 拆分应用程序包 │
│ (React、RN、Vega) │ │(应用程序专属代码)│
└────────────────────┘ └─────────────────────┘
在运行时,Vega首先加载系统包,然后将之拼接到您拆分出的应用程序包中。
为什么拆分包很重要
拆分包可带来几个关键优势:
- 应用程序更小 — 从应用程序包中移除常用库可将其大小减少1MB或更多。
- 启动时间 (TTFD) 更快 — 核心库已预装在设备上,可将应用程序初始化时间缩短约100至150ms。
- 自动错误修复 — 由于系统库是独立更新的,因此无需发布新的应用程序版本即可修复错误并提高性能。
- 兼容性问题更少 — JS和原生组件都位于同一系统版本中,可确保兼容性。
拆分包机制的工作原理
在底层实现上,拆分包机制依赖于扩展Metro,它是React Native使用的JavaScript打包工具。通常,Metro会生成一个包含所有应用程序代码和依赖项的单一index.bundle包。为启用拆分,Vega对Metro的序列化器阶段进行了自定义改造,该阶段负责控制如何将模块组合成包。
为实现这一点,需用到两个关键钩子:
processModuleFilter
- 筛除系统包中已提供的模块。
- 确保应用程序包不会重复包含诸如
react或react-native这类库。
createModuleIdFactory
- 用于为模块分配一致的确定性ID,确保系统包和应用程序包在共享代码时引用相同的模块ID。
- Vega不使用Metro的默认增量ID,而是使用基于哈希的方案(例如模块路径的SHA-256)来保证其在构建过程中的稳定性。
构建时 运行时
──────────────────► ───────────────►
┌─────────────┐ ┌──────────────┐ 使用 ID 于 ┌───────────────┐
│ 源包 │─► │ 核心包 │───────────────► │ 加载核心包 │
│ (应用 + 库) │ │ (React, RN, │ │ (系统级) │
└─────────────┘ │ Vega) │ └───────────────┘
└─────┬────────┘
│ 写入 modules.txt
▼
┌──────────────┐ 使用 ID 于 ┌───────────────┐
│ 库包 │───────────────► │ 加载库包│
│(例如 rnsCRN)│ │(系统级)│
└─────┬────────┘ └───────────────┘
│ 重复使用 ID / 过滤
▼
┌──────────────┐ ┌───────────────┐
│ 应用包 │───────────────► │ 加载应用包 │
│(拆分)│ │(在之上)│
└──────────────┘ └───────────────┘
包的类型
分包系统创建了三类主要的包:
核心包(系统级)
- 包含重要的基础库 (
react,react-native,@amazon-devices/react-native-kepler), - 它是首先生成的,会创建一个
modules.txt文件,用于将模块路径映射到ID, - 从而保障后续依赖包中的模块引用保持一致。
库包(系统级)
- 适用于常见的库,例如
react-native-reanimated或react-native-screens, - 构建时会利用核心包所创建的
modules.txt,以避免重复打包已经打包的依赖项。 - 会为每个库包生成额外的
modules.txt文件。
应用包(拆分后的应用包)
- 您的应用程序代码会经过过滤,剔除掉系统包中已包含的任何内容。
- 通过共享的统一ID来引用系统提供的模块。
构建时会生成诸如keplerscript-app-system-bundles-config.json之类的元数据,告诉Vega您的应用需要哪些系统包。运行时,Vega会先加载系统包,再将应用包挂载到之上。
依赖项与版本管理
分包机制的一大核心挑战就是依赖版本管控:
- 如果系统预装包内置的是
react-native-screens@2.0.0, 但你的应用需要的是2.1.0,将可能引发冲突。 - 为解决这类冲突,Vega在内部采用带版本标识的模块路径,例如
react-native-screens__2/。 - 仅会将主要版本编码到路径中,例如
__2/,因此从2.0.0到2.0.1这类补丁更新,不会破坏兼容性,也不会强制应用程序重新构建。
筛选依赖项时:
系统包会包含自己的依赖项,例如lodash,但不会在modules.txt中予以列出。因此,如果应用程序也依赖于相同版本的lodash,则它仍存在于应用程序包中,以防止系统库升级时意外损坏。
主要版本相同,可安心升级:@amzn /react-native-screens__2/... (2.0.0 → 2.0.1 的升级,不会改变路径)
主要版本不同,则特意区分:@amzn /react-native-screens__3/...
这套方案搭配稳定的模块ID机制,能让系统包高频迭代更新的同时,始终保持与应用的兼容性。
系统包构建全生命周期
以下是分包构建的完整生命周期:
- 生成核心包 — 包含React、React Native和Vega模块。
- 生成库包 — 使用基于核心包的
modules.txt的依赖项感知过滤。 - 生成应用程序包 — 删除系统已提供的所有模块。
- 生成元数据 — 列出应用程序需要哪些系统包。
- 加载Vega — 首先加载系统包,然后挂载应用程序包。
最终形成模块化体系,让应用体积更小、启动更快,同时对底层库版本更新具备更强的抗干扰能力。
相关主题
- 适用于Vega应用程序架构的React Native — 涵盖了Vega背后的更广泛的架构决策,包括如何将React Native运行时内置到操作系统中以及如何与应用程序进行动态链接。
- 支持的库和服务 — 列出所有随系统包预装分发的库,同步标注对应版本号与兼容性说明。
- 使用VMRP在您的应用程序中导入库 — 为不支持标准npm别名与覆盖规则的分包场景讲解模块解析配置方法。
- 应用程序性能最佳实践 — 提供系统分包自动优化之外的进阶技巧,进一步缩减包大小,提升应用启动速度。
- 安装和配置 Vega ESLint 插件 — 内置校验规则,自动检查
package.json中系统分发库的使用情况,标记出在分包场景下行为异常的导入。
Last updated: 2026年4月16日

