文档详情

ReactNative中实现动态导入的示例代码.docx

发布:2025-06-02约8.68千字共12页下载文档
文本预览下载声明

ReactNative中实现动态导入的示例代码

目录背景多业务包动态导入Metro打包原理打包过程bundle分析__d函数__r函数方案设计分识别入口树拆分bundle生成合总结

背景

随着业务的发展,每一个ReactNative应用的代码数量都在不断增加,bundle体积不断膨胀,对应用性能的负面影响愈发明显。虽然我们可以通过ReactNative官方工具Metro进行拆包处理,拆分为一个基础包和一个业务包进行一定程度上的优化,但对日益增长的业务代码也无能为力,我们迫切地需要一套方案来减小我们ReactNative应用的体积。

多业务包

第一个想到的就是拆分多业务包,既然拆分为一个业务包不够,那我多拆为几个业务包不就可以了。当一个ReactNative应用拆分为多个业务包之后其实就相当于拆分为多个应用了,只不过代码在同一仓库里。这虽然可以解决单个应用不断膨胀的问题,但是有不少局限性。接下来一一分析:

链接替换,不同的应用需要不同的地址,替换成本较高。页面之间通信,之前是个单页应用,不同页面之间可以直接通信;拆分之后是不同应用相互通信需要借助客户端桥接实现。性能损耗,打开每个拆分的业务包都需要单独起一个ReactNative容器,容器初始化、维持都需要消耗内存、占用CPU。粒度不够,最小的维度也是页面,无法继续对页面中的组件进行拆分。重复打包,部分在不同页面之间共享的工具库,每个业务包都会包含。打包效率,每一个业务包的打包过程,都要经过一遍完整的Metro打包过程,拆分多个业务包打包时间成倍增加。

动态导入

作为一个前端想到的另一方案自然就是动态导入(Dynamicimport)了,基于其动态特性对于多业务包的众多缺点,此方案都可避免。此外拥有了动态导入我们就可以实现页面按需加载,组件懒加载等等能力。但是Metro官方并不支持动态导入,因此需要对Metro进行深度定制,这也是本文即将介绍的在ReactNative中实现动态导入。

Metro打包原理

在介绍具体方案之前我们先看下Metro的打包机制及其构建产物。

打包过程

如下图所示Metro打包会经过三个阶段,分别是Resolution、Transformation、Serialization。

image

Resolution的作用是从入口开始构建依赖图;Transformation是和Resolution阶段同时执行的,其目的是将所有module(一个模块就是一个module)转换为目标平台可识别语言,这里面既有高级JavaCript语法的转换(依赖BaBel),也有对特定平台,比如安卓的特殊polyfills。这两个阶段主要是生产中间产物IR为最后一阶段所消费。

Serialization则是将所有module组合起来生成bundle,这里需要特别注意MetroAPI文档中SerializerOptions中的两个配置:

签名为createModuleIdFactory,type为()=(path:string)=number。这个函数为每个module生成一个唯一的moduleId,默认情况下是自增的数字。所有的依赖关系都依仗此moduleId。签名为processModuleFilter,type为(module:Array)=boolean。这个函数用来过滤模块,决定是否打入bundle。

bundle分析

一个ReactNative典型的bundle从上到下可以分为三个部分:

第一部分为polyfills,主要是一些全局变量如DEV;以及通过IIFE声明的一些重要全局函数,如:__d、__r等;第二部分是各个module的定义,以__d开头,业务代码全部在这一块;第三部分是应用的初始化__r(react-native/Libraries/Core/InitializeCore.jsmoduleId)和__r(${入口moduleId})。

我们看下具体函数的分析

__d函数

functiondefine(factory,moduleId,dependencyMap){

constmod={

dependencyMap,

factory,

hasError:false,

importedAll:EMPTY,

importedDefault:EMPTY,

isInitialized

显示全部
相似文档