bundle的拆包

RN的默认机制是加载一个bundle,并且在初始化就加载。不利于我们的业务维护,所以要拆包。

主要是拆分成基础包CommonBundle + N个业务包。

初始化ReactContext—->ReactManager

达到的目标:

  1. ReactNative的动态加载与卸载。
  2. bundle的拆分与加载。包名+类名
    使用metro-bundle.js类来

主流方案diff-match-patch

简介:Google提供,用来对比两个文件内容,求出差异内容

拆包思路:打一个空View的jsbundle生成基础包,再打一个包含业务代码的包生成全量包,然后通过diff-match-patch对比全量包和基础包生成差异包即业务包

优点:
操作简单

缺点:
diff-match-patch 得到业务包和基础包的差异文本记录,除了记录单纯的业务代码差异外,还加入了额外且多量的补丁信息
diff-match-patch 的patch_apply方法在Android中存在严重的效率问题,性能一般的机型,合并较大补丁文件效率会更低

metro bundle

简介: facebook提供,是react-native的官方打包及dev server工具。官网:https://facebook.github.io/metro/

拆包思路:
通过metro打包,打基础包和全量包都要通过createModuleIdFactory固定 module 的ID,然后用processModuleFilter过滤掉全量包中基础包的内容模块。

优点:

  • Metro 的高度可扩展性
  • 操作配置简介,不需要改动源码
  • 官方维护,随RN版本的迭代不断完善

这个就是现在rn版本使用的打包工具,是由之前的rn打包代码中抽取出来成为一个单独的项目,metro更新迅速,一个月一个样,现在我觉得已经比较完善了,可以拿出来溜溜

全新的做法

其实react native在0.5时代就已经引入了metro bundle,但由于其还是在不断完善,无法完成分包大任,现在0.57已经可以完全支持分包了

其实react native打包是支持配置的:https://facebook.github.io/metro/docs/en/configuration

配置是不是眼花缭乱,分包只要用到两个配置:createModuleIdFactory和processModuleFilter

createModuleIdFactory函数传入的是你要打包的module文件的绝对路径返回的是这个module的id

processModuleFilter函数传入的是module信息,返回是boolean值,如果是false就过滤不打包

做法就很清晰了,配置createModuleIdFactory让其每次打包都module们使用固定的id(路径相关),

配置processModuleFilter过滤基础包打出业务包

具体的配置看我的github吧
加载多bundle

现在网上流传的一些方法都还是demo级别的方法,我的做法是尽量与react native兼容

android是直接重写ReactActivity,只在运行module前加载了业务包文件,这样可以让代码有完整的生命周期

iOS监听基础包加载成功的消息,基础包加载后再加载业务包,顺序和时机都是完美

react-native-multibundler

下载下来

CRN

简介:由携程无线平台研发团队基于React Native框架优化,定制成稳定性和性能更佳、也更适合业务场景的的跨平台开发框架

拆包思路:

生成框架jsbundle

业务代码拆分主要是把中间框架/业务模块定义给拆分开来,拆分的思路很简单,用一个空白页面作为入口点,AppRegistry.registerComponent加载这个入口点。进入业务时,通过这个入口点页面去加载真实的业务代码。把这个空白的入口点页面作为框架的一部分,通过react-native bundle命令打包成框架jsbundle。

抽取业务js代码

对React Native unbundle的打包过程进行定制,首先让iOS支持unbundle打包(默认是不支持的), 将生成的业务js模块代码单独保存,每个js模块一个文件,文件名即为模块ID.js;

js模块加载优化

空白页面入口组件,要能加载(require)真实的业务代码,我们需要改造RN的require方法,简单修改Native SDK中的JSCExecutor(RCTJSCExecutor.mm/JSCExecutor.cpp)文件,调整nativeRequire实现即可。

优点:

工程化配套完整
拆包体积优化明显
首屏时间缩减显著
预加载、按需加载

问题:

文档资料少,上手较难
改动源码多
以后升级局限于CRN框架维护程度

其他

在网上查了相关的资料,主流的方案基本都是把Main.jsbundl拆分成基础包common.jsbundle+业务包bundle,和上面拆包目标基本一样,不赘述。

具体的拆分思路就很不一样了:

1. QQ音乐

https://cloud.tencent.com/developer/article/1032279

侵入RN代码,修改打包流程,使得打出来的包就是基础+业务包,如QQ音乐

https://cloud.tencent.com/developer/article/1005415

2. 在RN打包的基础上,实现新的打包方案,如携程 moles-Packer

简介:携程大厂推出,稳定可靠,针对react native0.44时代的版本

优点:重写了react native自带的打包工具,重写就是为了分包,为分包而生的项目,肯定可靠

缺点:2 years ago,只适合rn老版本用户了,现在都9012了,0.5以上的rn版本全部扑街

3. Patch方案,打包流程不变,生成基础包后,根据diff来生成每个业务不同的patch包

简介:大致的做法就是先打个正常的完整的jsbundle,然后再打个只包含了基础引用(react和第三方module)的基础包,比对一下patch,得出业务包,这样基础包和业务包都有了

优点:简单暴力,如果只是想简单做下分包的可以尝试下

缺点:1、不利于维护,由于module后面都是rn生成数字,依赖变了数字也变,导致基础包变了所有包都需要变2、图片没法分包,有的第三方库是有图片的,这个方法只处理jsbundle不处理图片

具体实施

有了基础包入口文件base.js,然后就可以配置metro.config.js了

文章目录
  1. 1. 主流方案diff-match-patch
  2. 2. metro bundle
  3. 3. CRN
  4. 4. 其他
    1. 4.1. 1. QQ音乐
    2. 4.2. 2. 在RN打包的基础上,实现新的打包方案,如携程 moles-Packer
    3. 4.3. 3. Patch方案,打包流程不变,生成基础包后,根据diff来生成每个业务不同的patch包
  5. 5. 具体实施
本站总访问量 本站访客数人次 ,