ReactNative系列之三十一业务bundle拆分及动态加载实例

2023-10-26

-------------------2018-12-17日志-------------------

1.github上的源代码更新,修复windows上生成bundle内路径的异常处理

--------------------------

暂时先放出思路,近期会做一期视频解析及源码下载:敬请关注

演示视频:https://pan.baidu.com/s/1FYVYgSezBvT3kvjRlbmzEw

源码下载: https://github.com/feixue1232/react-native-split-index ,求 start ~~~

前言:此步骤完成ReactContext的动态加载与卸载、bundle的拆分、bundle的索引以字符串形式(默认为int形式)解耦~~

第3步之后的每一步将为大家从0开始一步步的去完成建立一个ReactNative项目的支持多业务并且,根据业务模块进行Bundle的灵活拆分,便于业务的灵活扩展~ 总体为common.bundle(1个基础模块)+business.Bundle(N个)。亮点是还可以完成当common.bundle升级后,不会对业务bundle造成影响。

bundle拆分加载

如果创建ReactNative项目失败,可以尝试以下1、2;

1.设置taobao国内镜像库路径

npm config set registry https://registry.npm.taobao.org

npm config set disturl https://npm.taobao.org/dist

2.升级NodeJs版本

sudo npm cache clean -f

sudo npm install -g n

sudo n stable

3.首先创建一个项目,版本为0.50

react-native init split --version 0.50.0

4.编写业务模块A、业务模块B的代码,分别引用common模块。

1)common模块中的类需要由一个总的索引文件进行import.

2))业务模块中的索引文件(就是打包的注册的启动js)需要在文件的第一行引入common中的索引文件

这样做的好处理:方便comm命令进行文件的差分处理。即保证两个文件重复的部分都是头部,否则可能会造成comm比对有部分行失误。

5.我们需要修改下源码,修改源码的目标在于(这块是重点):

1)改造项目,编译ReactNative源码

2)打开Bundle文件,我们会发现每一个__d(function(){}, moduleId), 都有这样的结构,moduleId默认类型为number型,每一个number都是唯一的,通过这个值来索引一个类,用于bundle文件中的内在关联。但是我们需要思考一个问题,当common.bundle的范围是0-100时,业务a为101-200,业务b为201-300时,我们需要解决,common.bundle的及业务a的文件变动。当一个底层的文件发生变动时,分配的moduleId就会有所改变,影响到上层的引用关联。就会出异常!所以我们可以这样做,把分配的moduleId,改变一下形如‘com.yeputiWK.business.Index.page’这样的串时,并且package+类名本身具有唯一性,这样就充分的在各bundle模块中的索引解耦。

从源代码编译ReactNative参考:https://reactnative.cn/docs/building-from-source/ 

编译过程中如果出错请参考:https://blog.csdn.net/yeputi1015/article/details/81487754

6.需要修改metro-bundle源码中的代码,修改3部分内容。

1)类中的require的类

2)各个类自身的索引

3)文件最最底部的,总体require入口

涉及到两个类的修改:

node_modules/metro-bundler/src/Bundler/Bundler.js   修改"3)"中的内容,涉及方法为:

_addRequireCall

node_modules/metro-bundler/src/Resolver/index.js  修改"1)、2)"中的内容,涉及方法为:

resolveRequires   、   wrapModule  及  defineModuleCode

7.打包、拆分包、差分包可以编写一个sh批处理文件,如下:

#------------------
#   echo_color
#   对于一些特殊操作进行颜色提示
#------------------
echoc()
{
    echo -e "\033[36m $1 \033[0m"
}

#-------------------------------
#   echo_error
#   执行过程中产生错误的的信息提示
#-------------------------------
echoe()
{
    echo -e "\033[31m $1 \033[0m"
}

echoc "rn.sh react_native_bundle"
echoc "生成common.bundle"
react-native bundle --platform android --dev false --entry-file common/index.js  --bundle-output android/app/src/main/assets/common.bundle  --assets-dest android/app/src/main/res/
echoc "生成subA.bundle"
react-native bundle --platform android --dev false --entry-file subA/subA.js  --bundle-output android/app/src/main/assets/subA.bundle  --assets-dest android/app/src/main/res/
echoc "生成subB.bundle"
react-native bundle --platform android --dev false --entry-file subB/subB.js  --bundle-output android/app/src/main/assets/subB.bundle  --assets-dest android/app/src/main/res/
echoc "生成subC.bundle"
react-native bundle --platform android --dev false --entry-file subC/subC.js  --bundle-output android/app/src/main/assets/subC.bundle  --assets-dest android/app/src/main/res/
echoc "生成差分subA_.bundle文件"
comm -2 -3 android/app/src/main/assets/subA.bundle android/app/src/main/assets/common.bundle > android/app/src/main/assets/subA_.bundle
echoc "生成差分subB_.bundle文件"
comm -2 -3 android/app/src/main/assets/subB.bundle android/app/src/main/assets/common.bundle > android/app/src/main/assets/subB_.bundle
echoc "生成差分subC_.bundle文件"
comm -2 -3 android/app/src/main/assets/subC.bundle android/app/src/main/assets/common.bundle > android/app/src/main/assets/subC_.bundle

8.动态加载和卸载ReactContext部分

1)程序依然需要继承ReactApplication,并且需要返回ReactNativeHost,host中指定common.bundle

2)在Activity中可通过获取Application中的host去手动加载ReactContext,实际上加载了common.bundle:

((ReactApplication)getApplication()).getReactNativeHost().getReactInstanceManager().createReactContextInBackground();

3)卸载ReactContext

((ReactApplication)getApplication()).getReactNativeHost().getReactInstanceManager().destroy();

4)子业务的加载,当然可以跟据业务需求手动加载,这里我在common.bundle加载成功后的listener里加载所有的业务bundle:

private void createContext() {
    Log.e(TAG, "wk start createContext");
    SoLoader.init(this, /* native exopackage */ false);
    final ReactInstanceManager manager = ((ReactApplication)getApplication()).getReactNativeHost().getReactInstanceManager();
    if (!manager.hasStartedCreatingInitialContext()) {
        manager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
            @Override
            public void onReactContextInitialized(ReactContext context) {
                onContextInitialized();
            }
        });
        ((ReactApplication)getApplication()).getReactNativeHost().getReactInstanceManager().createReactContextInBackground();
    }
}

private void onContextInitialized() {
    text.setText(loaded);
    Toast.makeText(getApplicationContext(), "ReactContext初始化完毕", Toast.LENGTH_LONG).show();
    Log.e(TAG, "wk onContextInitialized");
    loadBundleFromAssets("subA_.bundle");  // 加载子业务bundleA
    loadBundleFromAssets("subB_.bundle");  // 加载子业务bundleB
    loadBundleFromAssets("subC_.bundle");  // 加载子业务bundleC
}

private void loadBundleFromAssets(String bundlepath) {
    String source = "assets://" + bundlepath;
    Log.e("RNN", "wk loadScriptFromAsset:"+source);
    try {
        Method method = CatalystInstanceImpl.class.getDeclaredMethod("loadScriptFromAssets",
                AssetManager.class,
                String.class,
                boolean.class);
        method.setAccessible(true);
        method.invoke(((ReactApplication)getApplication()).getReactNativeHost().getReactInstanceManager().getCurrentReactContext().getCatalystInstance(), this.getAssets(), source, false);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

9)图片资源的处理,在使用打包命令时。被将js中引用到的图片,放入res目录下,并重命名(跟据的规则为包名+文件名,包名间以下划线分隔)。可查看源码中的resolveAssetSource.js了解相关的加载路径的识别

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ReactNative系列之三十一业务bundle拆分及动态加载实例 的相关文章

  • Sophus库:对SO(3)和SE(3)的构建及扰动模型搭建

    简介 使用Eigen库中Geometry模块能够实现对 S O 3 SO 3 SO 3 S
  • 微信开发者工具的版本控制

    注意事项 拉取代码时 应先关闭所有的编辑器代码页面 清理版本管理工具里的工作区 保存到本地 不管什么时候 需要把代码提交到线上的请先拉取一下线上代码 一 提交代码流程 先在 微信开发者工具 的 版本管理 中把代码存储在本地分支上 拉取线上分
  • 用js实现简单的满屏跳动的心

    用js实现简单的满屏跳动的心
  • 实施MES系统的成功率只有50%,你知道为什么吗?

    MES系统可以称之为生产制造产业生产和管理方法实现代化的管理中心 假如可以非常好的执行和运用MES 那么将有益于提升公司的生产率 降低消耗成本 但为什么会有些公司MES执行实际效果不佳呢 原因之一 我国制造业存在管理方法基础的先天发育不足
  • Android中LCD背光驱动

    分类 Linux驱动 Android系统 2013 06 17 16 28 287人阅读 评论 0 收藏 举报 目录 Android的Setting Android的背光JNI层 Android的背光HAL层 Linux的背光内核层 Lin
  • 【web基础】html常用标签+作品展示

    前言 小亭子正在努力的学习编程 接下来将开启javaEE的学习 分享的文章都是学习的笔记和感悟 如有不妥之处希望大佬们批评指正 同时如果本文对你有帮助的话 烦请点赞关注支持一波 感激不尽 说明 此部分是java web基础知识 学的不深 仅
  • python爬虫万能模板

    以下是一个简单的 Python 爬虫模板 可以用于爬取网页数据 python import requests from bs4 import BeautifulSoup 设置请求头 模拟浏览器访问 headers User Agent Mo
  • kubectl命令详解

    目录 一 kubectl命令详解 1 查看某个资源的详细信息 kubectl describe pod pod name n nameapace 2 查看指定命名空间中pod的基本信息 kubectl get pods n namespac
  • kubernetes自建单节点elasticsearch ,用做数据库

    apiVersion v1 kind ConfigMap metadata name es configmap namespace kube system data elasticsearch yml cluster name NAMESP
  • redis key以目录展示的算法 以及其他redis相关

    文章目录 前言 一 redis相关 二 目录展示算法 结果展示 前言 一般在开发中使用redis时 都会使用冒号进行key的分割 例如login token admin等等 最近被要求编写可视化redis管理的工具 要以树形文件夹目录展示r
  • 环境类传感器介绍

    经过前几篇的原理讲解 大家对市面上类似气体 PM2 5 火焰呀这类传感器有一定的了解 但是到采购环节就迷茫了 毕竟市面上的产品五花八门 挑的眼花缭乱 今天给大家介绍几款简单的传感器 如果大家有别的传感器 也可以采用 甲醛检测 ZE08 CH
  • unity2017Progressive Lightmapper,Navmesh,Timeline三大新特性总结

    今天看了刘国柱的unity2017新特性 keynote大会三大核心详解视频课程 以免忘记 所以总结了下 想要具体了解的话可以去51cto观看刘国柱的视频 一 更强大的图像处理 1 Progressive LightMapper 2 新灯光
  • 如何计算Map

    一 VOC07 11点计算法 在VOC2010以前 只需要选取当Recall gt 0 0 1 0 2 1共11个点时的Precision最大值 然后AP就是这11个Precision的平均值 在VOC2010及以后 需要针对每一个不同的R
  • MySQL查询条件中字符串包含空格的问题

    2013 11 27 wcdj 问题 最近在联调某个业务时发现使用的签名总是验证不过 在MySQL中查询了该业务的私钥配置和业务侧的配置是一样的 问题就出在SQL查询这里 最后将配置导出到本地发现私钥后面多了一个空格 将空格删除然后签名计算
  • table嵌套table

  • QT 打开txt文件以及出现的乱码问题

    在用QT实现记事本打开功能时 在导入txt文件后会出现乱码问题 这时需要对导入文件编码进行设置 代码如下 void MainWindow open QString fileName 弹出打开文件对话框 fileName QFileDialo

随机推荐

  • Vb仓库管理系统与实现(论文+源代码+开题报告+外文翻译+文献综述)

    随着科学技术的不断提高 计算机科学不断发展 其强大的功能已经被人们深刻认识 它已经进入了人类社会的各个领域并发挥着越来越重要的作用 作为计算机应用的一部分 使用计算机对产品库存信息进行管理 是一直必然的趋势 本文主要分析了库存管理系统的一些
  • 在iOS开发中使用FMDB

    我的第一个应用使用的数据库是操作sqlite3 熟悉了之后 还不愿意换了 说实话这个方法并不是很轻量级 繁琐 复杂的数据读取插入后果就是崩了 我知道很大一部分原因是因为我的线程没处理好 出现死锁 逻辑混乱导致的 所以我想使用更轻量级的数据库
  • 离散数学:主范式(主析取范式、主合取范式)

    求解主析取范式 主合取范式方法 1 真值表法 在表中列出变元值的全部可能 查表判断命题 命题结果真 变元值对应主析取范式 命题结果假 变元值对应主合取范式 2 等值演算法 命题化简 蕴涵等值式 A B A B 作用 去 矛盾律 A A 作用
  • Latex作者上标和通讯作者图标

    作者上标 author Lily textsuperscript 1 and Alexw textsuperscript 2 通讯作者图标 usepackage misc ifsym begin document institute Let
  • fs 模块

    fs 全称为 file system 称之为 文件系统 是 Node js 中的 内置模块 可以对计算机中的磁盘进行操作 本章节会介绍如下几个操作 1 文件写入 2 文件读取 3 文件移动与重命名 4 文件删除 5 文件夹操作 6 查看资源
  • 数据结构笔记 第六章 查找技术

    查找技术 在计算机科学中定义为 在一些 有序的 无序的 数据元素中 通过一定的方法找出与给定关键字相同的数据元素的过程叫做查找 也就是根据给定的某个值 在查找表中确定一个关键字等于给定值的记录或数据元素 线性表的查找技术 顺序查找 顺序查找
  • 【报名中】【5G探索】深度揭秘5G核心技术与挑战,云+社区开发者大会北京站等你来!

    报名渠道 扫描下方二维码 开发者专属福利 限量手办 现场幸运签到开发者即可获得 早到获奖几率更大 幸运抽奖 一等奖 1名 JBL LIVE650 BTNC无线主动降噪智能耳机 二等奖 3名 JBL GO SMART2 音乐魔方二代便携式人工
  • Thread类常见方法及属性及线程的状态

    本篇文章思维导图如下 目录 Thread构造方法 Thread常见属性 守护线程 start 方法 创建一个线程 中断线程 总结一下interrupt方法 等待线程 join 休眠线程sleep 线程的状态 Thread构造方法 Threa
  • 实验一 以太网组建

    实验一 以太网组建 一 实验目的和要求 1 认识交换机和路由器的结构与连接方法 2 区分直通线和交叉 3 掌握简单的局域网配置方法以及组网方法 4 了解ip地址的组成 5 了解子网掩码 MAC 默认网关 数据链路地址的概念 6 了解配置路由
  • 区块链到底是什么?

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 翻译人 ArrayZoneYour 该成员来自云 社区翻译社 原文链接 https www investinblockchain com what exactly is blockc
  • 936焊台(恒温电烙铁)温度不可调的维修 (Z)

    Original Address http www zhaoniupai com archives 162 html 1 产线送来一台深圳山寨白光SBK 936焊台 恒温电烙铁 温度高且不可调 即使旋回220最低温度处 烙铁的温度也很高 锡
  • Maven 常用配置

    常用命令 打包指定模块 跳过测试 mvn clean package pl web am Dmaven test skip true 打包并构建docker镜像 详情参考 https blog csdn net u014438244 art
  • 地理坐标系和投影坐标系之间的关系

    转自 http blog csdn net qq 34149805 article details 65634252 基本概念 地理坐标系 为球面坐标 参考平面地是椭球面 坐标单位 经纬度 投影坐标系 为平面坐标 参考平面地是水平面 坐标单
  • C# 串口接收1次数据会进入2次串口接收事件serialPort1_DataReceived,第2次进入时串口缓冲区为空

    在C 中使用串口接收数据时发现 在完整的接收完一次数据后 还会再次进入串口接收事件 在网上搜索资料发现其他开发者也有遇到该问题 1 c 串口事件接受一次数据莫名其妙会触发两次 原文链接 https www 52pojie cn thread
  • 剑指Offer 06.从尾到头打印链表

    原题链接 思路 首先扫描一遍链表 算出链表中有多少个元素 再一次扫描链表 映射到数组的相应位置上就行 如果说 链表中 3 个元素 第一个元素对应的位置就是 2 第二个元素对应的位置就是 1 第三个元素对应的位置就是 0 代码 class S
  • UGUI聊天消息气泡随文本内容自适应

    游戏中需要用做UGUI做聊天界面 其中聊天气泡ChatItem的UI要求能随着聊天内容文本的长度自适应的 网上搜了一下聊天气泡的UI 发现都不太符合咱的需求 具体来说是文本宽度不足一行时 文本宽度自增 文本宽度大于一行时 文本高度自增 效果
  • 大数据导论学习日志Day1

    第一章大数据概述 1数据 1 1数据的概念 数据是指对客观事件进行记录并可以鉴别的符号 是对客观事物的性质 状态以及相互关系等进行记载的物理符号或这些物理符号的组合 是可识别的 抽象的符号 数据和信息是两个不同的概念 信息是较为宏观的概念
  • mysql 唯一索引为null_mysql 唯一索引与null.md

    mysql 的唯一索引要求所有参与的列都不能够为 null 值 如果唯一索引中的任何一个元素含有 null 值 则唯一约束将不起作用 示例代码 create table tb a int b int c int unique index a
  • go并发爬虫

    说明 最大20线程 搜索深度不大于3的网页 并打印出来 当搜索的不是网页的时候 存在bug 还在学习 希望有大佬告知怎么解决 package main import fmt log net http golang org x net htm
  • ReactNative系列之三十一业务bundle拆分及动态加载实例

    2018 12 17日志 1 github上的源代码更新 修复windows上生成bundle内路径的异常处理 暂时先放出思路 近期会做一期视频解析及源码下载 敬请关注 演示视频 https pan baidu com s 1FYVYgSe