首页> 中国专利> ReactNative框架中实现bundle的模块化打包处理的系统

ReactNative框架中实现bundle的模块化打包处理的系统

摘要

本发明涉及一种ReactNative框架中实现bundle的模块化打包处理的系统,包括module定义模块,用于将以数字id来标识module修改为以具有业务含义的字符串来标识;主bundle编译模块,用于将ReactNative基础组件和项目代码打包成bundle文件;项目文件编译模块,用于每个文件生成对应的一个bundle编译产物;同步方式加载js模块,用于实现在js环境直接调用pmRequire来动态加载本地文件系统中的js文件;文件加载模块,用于加载打包生成的主bundle,并根据客户端中的配置下加载编译产物的js文件。采用了本发明的ReactNative框架中实现bundle的模块化打包处理的系统,实现了将ReactNative的bundle拆分成主bundle和项目bundle,还实现了将项目bundle拆分成基于项目目录结构的单页面bundle。

著录项

  • 公开/公告号CN112181432A

    专利类型发明专利

  • 公开/公告日2021-01-05

    原文格式PDF

  • 申请/专利权人 普元信息技术股份有限公司;

    申请/专利号CN202011090847.5

  • 发明设计人 范岗民;刘磊;刘相;

    申请日2020-10-13

  • 分类号G06F8/41(20180101);G06F8/71(20180101);G06F8/73(20180101);G06F16/16(20190101);

  • 代理机构31002 上海智信专利代理有限公司;

  • 代理人王洁;郑暄

  • 地址 201203 上海市浦东新区中国(上海)自由贸易试验区碧波路456号4楼

  • 入库时间 2023-06-19 09:27:35

说明书

技术领域

本发明涉及移动App领域,尤其涉及基于ReactNative开发App领域,具体是指一种ReactNative框架中实现bundle的模块化打包处理的系统。

背景技术

在进入移动互联网时代,移动应用的开发效率也是企业发展重要的竞争力之一,ReactNative作为Facebook开源的跨平台应用开发框架,更是受到不少大公司的青睐。ReactNative并非使用传统的Webview渲染,而是采用JS桥接加Native桥接两个方式合并起来的。ReactNative产出的也不是网页应用,而是一个真正的移动应用。ReactNative使用JSX和CSS开发,学习成本相对于Android和iOS大大降低。同时它的bundle编译机制也使得应用在热更新领域会更加方便。但也是由于ReactNative将项目所有内容打包在一个bundle文件中,导致文件过大,从而在应用启动和首屏渲染上还有很大的提升空间。

ReactNative作为一款优秀的开源的跨平台应用开发框架,在国内已经有大量企业及个人用户使用,针对其bundle文件过大的问题,也有一些优秀的解决方案。

例如将打包产物分为两部分,首页和非首页的页面。为了加快页面打开速度,在打包时将首页和基础包编译为一个bundle文件,再将其他页面打包成一个bundle,在App启动时,只加载首页的模块,待首页模块加载完毕,再去异步加载后续页面的模块。当然,这不但需要修改多个页面的编译逻辑,还需要ReactNative原生代码提供支持。

还有一些分包的方式,比如使用Google的diff-match-patch工具计算业务patch,在集成到主工程并需要加载业务页面时,再合成一个完整的jsbundle进行加载。

现有技术下基于ReactNative打包过程相对复杂,打包产物也比较大,极大地限制了App首屏启动速度,同时也不利于应用的热更新。现有的分包方案也对ReactNative源代码修改过大,使用diff-match-patch工具时加载业务patch包的逻辑不可避免会变得比较复杂同时也存在效率问题,不利于ReactNative技术栈的持续实施。本专利将简化打包过程,同时打包产物结构清晰,方便管理,将ReactNative基础组件和App中页面分别独立打包,解决应用热更新的问题。统一编译生成的基础包也可以供多个项目组使用,解决ReactNative下多团队难以协同开发的问题。

发明内容

本发明的目的是克服了上述现有技术的缺点,提供了一种满足操作简便、协同开发方便、适用范围较为广泛)的ReactNative框架中实现bundle的模块化打包处理的系统。

为了实现上述目的,本发明的ReactNative框架中实现bundle的模块化打包处理的系统如下:

该ReactNative框架中实现bundle的模块化打包处理的系统,其主要特点是,所述的系统包括:

module定义模块,用于将以数字id来标识module修改为以具有业务含义的字符串来标识;

主bundle编译模块,与所述的module定义模块相连接,用于将ReactNative基础组件和项目代码打包成bundle文件,分别为主bundle打包文件和项目打包文件;

项目文件编译模块,与所述的主bundle编译模块相连接,用于在对项目大量文件进行编译时,每个文件生成对应的一个bundle编译产物;

同步方式加载js模块,与所述的项目文件编译模块相连接,用于通过在JSCExecutor.cpp文件中增加pmRequire,实现在js环境直接调用pmRequire来动态加载本地文件系统中的js文件;

文件加载模块,与所述的同步方式加载js模块相连接,用于加载打包生成的主bundle,并根据客户端中的配置下加载编译产物的js文件,加载得到入口页面module,传至主bundle中导航控制器,显示入口页面。

较佳地,所述的module定义模块取组件相对于node_modules目录的相对路径,通过修改打包过程中createModuleIdFactory函数替换module标识id。

较佳地,所述的主bundle打包文件为编译及打包ReactNative基础组件和入口导航器的文件。

较佳地,所述的项目打包文件为对单个文件进行编译并打包的文件。

较佳地,所述的主bundle打包文件通过配置的方式设置首页的module标识,并以此动态加载本地文件实现首页的展示。

较佳地,所述的配置方式为设置App项目内config.json文件的入口页面module标识字段,入口导航器通过获取该字段,以同步加载方式获取Component实现加载首页。

较佳地,所述的项目文件编译模块将文件编译成ReactNative中module定义的格式。

较佳地,所述的同步方式加载js模块直接读取本地文件系统中的js文件,并加载到ReactNative的js环境中。

较佳地,所述的文件加载模块对应多个目录,包括主bundle以及多个页面bundle。

采用了本发明的ReactNative框架中实现bundle的模块化打包处理的系统,实现了将ReactNative的bundle拆分成主bundle和项目bundle,还实现了将项目bundle拆分成基于项目目录结构的单页面bundle。由于bundle的拆分,解决了bundle文件过大的问题,显著提升了应用启动速度。另外,由于项目文件的bundle编译以及编译产物的统一管理,从而实现多团队使用同一套基础主bundle,提高团队开发协作能力。

附图说明

图1为本发明的ReactNative框架中实现bundle的模块化打包处理的系统的结构示意图。

图2为本发明的ReactNative框架中实现bundle的模块化打包处理的系统的同步方式加载js模块实现的示意图。

图3为ReactNative框架中实现bundle的模块化打包处理的系统的文件加载模块实现的示意图。

具体实施方式

为了能够更清楚地描述本发明的技术内容,下面结合具体实施例来进行进一步的描述。

本发明的该ReactNative框架中实现bundle的模块化打包处理的系统,其中包括module定义模块,用于将以数字id来标识module修改为以具有业务含义的字符串来标识;

主bundle编译模块,与所述的module定义模块相连接,用于将ReactNative基础组件和项目代码打包成bundle文件,分别为主bundle打包文件和项目打包文件;

项目文件编译模块,与所述的主bundle编译模块相连接,用于在对项目大量文件进行编译时,每个文件生成对应的一个bundle编译产物;

同步方式加载js模块,与所述的项目文件编译模块相连接,用于通过在JSCExecutor.cpp文件中增加pmRequire,实现在js环境直接调用pmRequire来动态加载本地文件系统中的js文件;

文件加载模块,与所述的同步方式加载js模块相连接,用于加载打包生成的主bundle,并根据客户端中的配置下加载编译产物的js文件,加载得到入口页面module,传至主bundle中导航控制器,显示入口页面。

作为本发明的优选实施方式,所述的module定义模块取组件相对于node_modules目录的相对路径,通过修改打包过程中createModuleIdFactory函数替换module标识id。

作为本发明的优选实施方式,所述的主bundle打包文件为编译及打包ReactNative基础组件和入口导航器的文件。

作为本发明的优选实施方式,所述的项目打包文件为对单个文件进行编译并打包的文件。

作为本发明的优选实施方式,所述的主bundle打包文件通过配置的方式设置首页的module标识,并以此动态加载本地文件实现首页的展示。

作为本发明的优选实施方式,所述的配置方式为设置App项目内config.json文件的入口页面module标识字段,入口导航器通过获取该字段,以同步加载方式获取Component实现加载首页。

作为本发明的优选实施方式,所述的项目文件编译模块将文件编译成ReactNative中module定义的格式。

作为本发明的优选实施方式,所述的同步方式加载js模块直接读取本地文件系统中的js文件,并加载到ReactNative的js环境中。

作为本发明的优选实施方式,所述的文件加载模块对应多个目录,包括主bundle以及多个页面bundle。

本发明的具体实施方式中,提供了一种App中ReactNative中bundle的模块化打包的方法。目前绝大多数使用ReactNative的App采用的是默认的bundle打包方式,该方式将App用到的所有组件、工具、页面全部打包到一个bundle文件中,这样会导致bundle文件过大,从而使应用启动过慢,同时由于bundle的不统一,多团队协作开发也无法进行。

本发明通过拆解bundle文件,实现模块化bundle打包,将bundle文件结构按照项目代码结构展开,项目中的每一个文件都会被打包成一个bundle产物,其中引用的系统及三方组件的模块标识与主bundle一致。极大方便了多团队项目管理、调试、热更新和组件化开发。

本发明通过通过重新定义module标识、解决了不同系统打包生成的bundle文件module标识不同的问题。通过将ReactNative基础组件和App中页面分别独立打包,解决当前基于ReactNative开发的App的bundle过大导致启动速度慢的问题,解决多团队难以协同开发的问题,解决无法差量热更新的问题。

一、本技术方案提供ReactNative中bundle的模块化打包和调试的方法,包括module定义模块,主bundle编译模块,项目文件(子bundle)编译模块,同步方式加载js模块,文件加载模块。

二、module定义模块

2.1、在ReactNative的bundle打包中,会将App用到的所有功能组件分别编译成单独的module,如下所示。

__d(function(global,_require,module,exports,_dependencyMap){

...

},0,[1,2,567,939],"index.js");

其中0、1、2、567、939分别代表了每个module的数字id,ReactNative通过自增数字id的方式定义和引用每个module。这种方法在单一bundle的场景下没有问题,但多bundle时会导致数字id会因为每次的编译而变化。

2.2、本发明将这种以数字id来标识module的方法修改为以具有业务含义的字符串来标识,如下所示。

__d(function(global,_require,module,exports,_dependencyMap){

...

},"react-native-cookies/index.js",["react/index.js","react-native/Libra ries/react-native/react-native-implementation.js","invariant/browser.js"],"node_modules/react-native-cookies/index.js");

其中react-native-cookies/index.js为该module的标识id,通过这种方式,可以做到不同项目打包得出的jsbundle产物中各module的标识相同且唯一。

2.3、本发明通过修改打包过程中createModuleIdFactory方法实现替换module标识id。本发明定义系统module标识的方法为取该组件(或js文件)相对于node_modules目录的相对路径。以下为部分关键代码。

2.4、将module标识由数字改为字符串后,在不同环境下编译bundle或编译单个文件,生成的module标识都一致。这样可以保证不同项目组协同开发时,可以共用一套基础bundle库,同时各自项目的文件module由于标识不同,也不会造成冲突。

三、主bundle编译模块

3.1、ReactNative的编译模式为将ReactNative基础组件和项目代码一起打包成一个bundle文件。本发明将打包分成了主bundle打包和项目打包。

3.2、(3.1)中所述主bundle打包为只编译ReactNative基础组件和入口导航器,将这部分编译成一个bundle文件。

3.3、(3.1)中所述项目打包为单个文件编译,详见模块4

3.2、其中主bundle中不包含具有任何具体业务含义的页面,通过配置的方式设置首页的module标识,并以此动态加载本地文件实现首页的展示。

3.3、(3.1)中所述ReactNative基础组件包括”react-native”和”react”组件。

3.4、(3.1)中所述入口导航器为ReactNative中的Navigator组件,通过设置Component来控制页面展示和页面跳转。

3.5、(3.4)中所述Component通过(5.1)的方法获取。

3.6、(3.2)中所述配置的方式为设置App项目内config.json文件的入口页面module标识字段。入口导航器通过获取该字段,以(5.1)中所述方法获取Component实现加载首页。

3.7、由于module的代码文件都会存在与用户本地目录node_modules下,所以我们将module标识字段的命名方式定为该文件相对于node_modules文件夹的相对路径,例如"react/index.js"。

3.8、主bundle中任意module编译出的module标识字段与(四)中子bundle编译流程中对应module编译出的module标识字段相同。

四、项目文件(子bundle)编译模块

4.1、代码文件以项目的形式存在,并分布在多个文件中。

4.2、传统的ReactNative编译是将所有的项目文件编译出来,并最终合并在一个文件里,形成单个bundle文件。

4.3、单个bundle的局限性有以下三点。

4.3.1、一般来说该文件会比较大(视项目规模而定),App启动时会加载该bundle文件,这是一个耗时的过程,会导致App启动变慢。

4.3.2、App在调试阶段,即时只修改了项目大量文件中的一个,ReactNative依然会重新编译所有的项目文件,同时App也会重新加载新编译出来的jsbundle,调试效率低。

4.3.3、App在更新时,即时只有单个文件的改动,依然需要重新编译整个项目,更新时也必须下载整个项目的编译产物,更新效率低。

4.4、本发明在对项目大量文件进行编译时,生成的产物也是大量单个文件,即项目中每个文件对应一个bundle编译产物,这样在应用启动时不需要加载整个ReactNative部分和项目产物的bundle部分,只需要加载ReactNative模块和项目首页相关的模块。

4.5、在调试和更新时,不需要更新整个bundle,而是只更新项目中修改的文件的编译产物即可。

4.6、在编译时,依然将文件编译成ReactNative中module定义的格式,如下

__d(function(global,_require,module,exports,_dependencyMap){

...

},"react-native-cookies/index.js",["react/index.js","react-native/Libra ries/react-native/react-native-implementation.js","invariant/browser.js"],"node_modules/react-native-cookies/index.js");

4.7、其中module标识的定义与上述module定义模块一致。

4.8、项目文件编译的产物为zip压缩包,其中目录结构与项目目录结构一致,产物内容其中js文件为编译模块产出的文件,其他文件与项目文件相同。

五、同步方式加载js模块

5.1、首先ReactNative未提供js环境中同步加载本地js文件的方法,而且js环境和原生通信是异步的,所以本发明通过在JSCExecutor.cpp文件中增加pmRequire方法,实现js环境直接调用原生c++中的pmRequire来动态加载本地文件系统中的js文件。

5.2、(5.1)中所述方法为通过c++直接读取Android/iOS本地文件系统中的js文件,并加载到ReactNative的js环境中,其中关键代码如下

5.3、(5.2)中所述本地文件系统中的js文件,为项目编译后的产物打包在App的安装包中,Android为apk包,iOS为ipa包。App安装启动后,会将项目编译产物拷贝到手机本地文件系统中,供App读取和加载。

5.4、(5.2)中所述的修改完成后,在Android中重新编译成so文件,产物由原项目引用,在iOS中直接修改该文件,从而实现js环境能够使用该方法。

5.5、本方法在js环境直接调用c++中定义的方法

5.6、加载module前,先判断是否存在,再判断是否已加载到内存中,若都没有,则去读取对应文件加载。

5.7、在(5.6)中module第一次加载成功之后,若有页面引用,则不会再次读取文件系统中的文件,而是从js环境中直接获取该module。

六、文件加载模块

6.1、应用打包时可以将(4.8)中编译产物放入项目assets目录下,应用首次启动时会将该zip文件拷贝到Android系统/data/data/下应用对应的目录。

6.2、应用启动时先去加载(3.2)中打包生成的主bundle,然后根据客户端中的配置去Android文件系统/data/data/目录下加载(4.8)编译产物的js文件。

6.3、加载得到入口页面module后,将其传给主bundle中导航控制器,从而显示入口页面。

本发明以某保险公司App为具体实施例说明本发明在ReactNative跨平台开发中的应用。

一、module定义模块

1.1、我们将这种以数字id来标识module的方法修改为以具有业务含义的字符串来标识,如下所示。

__d(function(global,_require,module,exports,_dependencyMap){

...

},"react-native-cookies/index.js",["react/index.js","react-native/Libra ries/react-native/react-native-implementation.js","invariant/browser.js"],"node_modules/react-native-cookies/index.js");

其中react-native-cookies/index.js为该module的标识id,通过这种方式,可以做到不同项目打包得出的jsbundle产物中各module的标识相同且唯一。

1.2、修改打包过程中createModuleIdFactory方法实现替换module标识id。本发明定义系统module标识的方法为取该组件(或js文件)相对于node_modules目录的相对路径。以下为部分关键代码。

1.3、将module标识由数字改为字符串后,在不同环境下编译bundle或编译单个文件,生成的module标识都一致。这样可以保证不同项目组协同开发时,可以共用一套基础bundle库,同时各自项目的文件module由于标识不同,也不会造成冲突。

二、主bundle编译

2.1、ReactNative的编译模式为将ReactNative基础组件和项目代码一起打包成一个bundle文件。我们将打包分成了主bundle打包和项目打包。

2.2、创建主bundle项目,其中引用”react-native”和”react”组件。

其中主bundle中不包含具有任何具体业务含义的页面,只包含ReactNative基础组件和项目需要使用的三方组件。

2.3、bundle项目中增加navigation导航器相关代码,控制页面加载及页面跳转,主要代码如下:

2.3、其中入口导航器通过获取客户端配置来加载入口页面module文件,并传给导航器,实现客户端首页的加载。

2.4、将主bundle项目通过(1.2)中所述的方法打包成一个主bundle文件,其中module的代码文件都会存在与用户本地目录node_modules下,所以我们将module标识字段的命名方式定为该文件相对于node_modules文件夹的相对路径,例如"react/index.js"。

2.5、主bundle中任意module编译出的module标识字段与(三)中子bundle编译流程中对应module编译出的module标识字段相同。

三、项目文件编译

3.1、代码文件以项目的形式存在,并分布在多个文件中。传统的ReactNative编译是将所有的项目文件编译出来,并最终合并在一个文件里,形成单个bundle文件。

3.2、单个bundle的局限性有以下三点。

3.2.1、一般来说该文件会比较大(视项目规模而定),App启动时会加载该bundle文件,这是一个耗时的过程,会导致App启动变慢。

3.2.2、App在调试阶段,即时只修改了项目大量文件中的一个,ReactNative依然会重新编译所有的项目文件,同时App也会重新加载新编译出来的jsbundle,调试效率低。

3.2.3、App在更新时,即时只有单个文件的改动,依然需要重新编译整个项目,更新时也必须下载整个项目的编译产物,更新效率低。

3.3、使用文件编译脚本编译整个ReactNative项目,将项目中所有的JS文件都编译成对应的单个bundle文件,并按照项目原结构分布。项目中非JS文件将直接拷贝到编译产物中。最终将编译产物zip压缩。

3.4、对项目大量文件进行编译时,生成的产物也是大量单个文件,即项目中每个文件对应一个bundle编译产物,这样在应用启动时不需要加载整个ReactNative部分和项目产物的bundle部分,只需要加载ReactNative模块和项目首页相关的模块。

3.5、项目在调试和更新时,不需要更新整个bundle,而是只更新项目中修改的文件的编译产物即可。

3.6、项目编译时,依然将文件编译成ReactNative中module定义的格式,

其中module标识的定义与上述module定义模块一致。

如下

__d(function(global,_require,module,exports,_dependencyMap){

...

},"react-native-cookies/index.js",["react/index.js","react-native/Libra ries/react-native/react-native-implementation.js","invariant/browser.js"],"node_modules/react-native-cookies/index.js");

四、页面加载

4.1、由于ReactNative未提供js环境中同步加载本地js文件的方法,而且js环境和原生通信是异步的,所以本发明通过在JSCExecutor.cpp文件中增加pmRequire方法,实现js环境直接调用原生c++中的pmRequire来动态加载本地文件系统中的js文件。

4.2、(4.1)中所述方法为通过c++直接读取Android/iOS本地文件系统中的js文件,并加载到ReactNative的js环境中,其中关键代码如下

4.3、(4.2)中所述本地文件系统中的js文件,为项目编译后的产物打包在App的安装包中,Android为apk包,iOS为ipa包。App安装启动后,会将项目编译产物拷贝到手机本地文件系统中,供App读取和加载。

4.4、(4.2)中所述的修改完成后,在Android中重新编译成so文件,产物由原项目引用,在iOS中直接修改该文件,从而实现js环境能够使用该方法。加载module前,先判断是否存在,再判断是否已加载到内存中,若都没有,则去读取对应文件加载。在module第一次加载成功之后,若有页面引用,则不会再次读取文件系统中的文件,而是从js环境中直接获取该module。

五、应用启动

5.1、客户端打包时将编译产物放入项目assets目录下,应用首次启动时会将该zip文件拷贝到Android系统/data/data/下应用对应的目录。

5.2、应用启动时先去加载(二)中打包生成的主bundle,然后根据客户端中的配置去Android文件系统/data/data/目录下使用(三)中所述方法加载编译产物的js文件。加载成功后会得到入口页面module,将其传给主bundle中导航控制器,从而显示入口页面。

采用了本发明的ReactNative框架中实现bundle的模块化打包处理的系统,实现了将ReactNative的bundle拆分成主bundle和项目bundle,还实现了将项目bundle拆分成基于项目目录结构的单页面bundle。由于bundle的拆分,解决了bundle文件过大的问题,显著提升了应用启动速度。另外,由于项目文件的bundle编译以及编译产物的统一管理,从而实现多团队使用同一套基础主bundle,提高团队开发协作能力。

在此说明书中,本发明已参照其特定的实施例作了描述。但是,很显然仍可以作出各种修改和变换而不背离本发明的精神和范围。因此,说明书和附图应被认为是说明性的而非限制性的。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号