当前位置: 首页 > news >正文

ReactNative项目构建分析与思考之RN组件化

传统RN项目对比

ReactNative项目构建分析与思考之react-native-gradle-plugin

ReactNative项目构建分析与思考之native_modules.gradle

ReactNative项目构建分析与思考之 cli-config

在之前的文章中,已经对RN的默认项目有了一个详细的分析,下面我们来看一下如何在已有项目中集成RN。

官方给了一个详细的文档,也比较简单。
这里就不再把文档中的内容重复了,直接来看一下跟默认项目的区别。

相同之处

  • 项目结构:两者项目结构基本相同,主要以RN的项目结构为核心,其中Android部分作为子目录集成于RN项目中。
  • 组织逻辑:都需要集成RN提供的插件以及native_modules脚本,来对项目进行组织和构建。

不同之处

  • UI处理方式
    • 默认项目:纯RN项目中,视图渲染是在Activity级别进行,所有视图均由RN渲染。
    • 集成到已有项目:视图的渲染粒度更为灵活,可以是Activity级别,也可以是Fragment或View级别。开发者可以根据具体业务需求,自由选择由RN还是原生代码来渲染视图,提供更加定制化的用户体验。
  • 定制化能力
    • 默认项目:定制化能力相对有限,主要依赖于RN官方提供的插件和组件。
    • 集成到已有项目:通过将RN作为组件集成,有更高的灵活性和定制化空间。可以根据业务需求开发专属的RN插件,还能在项目中灵活地利用RN的强大功能,从而实现更丰富和个性化的应用体验。

也就是说,两种方式在代码组织上并无本质上的区别,仅仅是在UI处理方式和定制化能力上有所不同。

RN项目搭建思考

找出核心点

对于RN官方给到我们的两种项目结构,实际上都是以RN为核心的,但是在实际的开发中,更多的是在已有项目中引入RN,我们更加希望RN作为原生项目的一个模块或者组件来进行混合开发。
例如下面这种组织结构:
在这里插入图片描述
react-native是Android工程中的一个模块,而不是 android 是RN项目下的一个子目录这种结构。

对于已有项目来说,需要考虑的是如何能够更简单的引入RN,尽量不要破坏Android项目的目录结构以及构建模式。
毕竟无论是目录结构的迁移还是构建模式的改变,都是一个非常大的工程。

要实现这种方式,实际上也比较简单,在前面的文章中,我们已经对RN的构建流程搞得比较清楚了。下面主要就是结合官方的在已有项目中集成RN的文档,稍作改造,集成到已有项目中即可。

参考在已有项目中集成RN的文档,相较于传统的Android项目,核心的点在于 React Native 相关的依赖需要从 node_modules 中引入 ,主要包括:

  • React Native 源码
  • React Native 插件:react-native-gradle-plugin
  • React Native 脚本:native_modules.gradle
  • React Native 中需要用到的原生模块:native module

其中,React Native源码和原生模块的引入是必须要处理的,因为他们是RN的核心部分。
而 react-native-gradle-plugin 和 native_modules.gradle 这两个插件是可选的,可以根据项目的实际情况来决定是否引入。

也就是说,核心的关键点在于,如何能够绕过 node modules 来解决掉依赖。

处理 React Native 的依赖

这里分两种情况

  1. 直接引入 Maven 仓库中的 React Native 依赖
  2. 自己编译 React Native 源码,打出 AAR 包引入

直接从 Maven 仓库中引入 React Native 依赖

从React Native 0.71.0版本开始,React Native提供了Maven仓库,可以直接从Maven仓库中引入React Native的依赖。

在这里插入图片描述

注意,这里的依赖是指React Native的Android部分,也就是react-android和hermes-android。

// https://mvnrepository.com/artifact/com.facebook.react/react-android
implementation("com.facebook.react:react-android:0.71.0")
implementation("com.facebook.react:hermes-android:0.71.0")

这种方式对于RN版本是0.71.0以上并且对源码没有定制要求的情况非常适用。

自己编译 React Native 源码,打出 AAR 包引入
在0.71.0版本之前,React Native没有提供Maven仓库,所以只能通过源码编译的方式来引入React
Native的依赖,或者使用传统的直接从nodu_modules中引入源码的方式。

在日常开发中,React Native源码本身存在一些bug或者不符合自身业务需求的地方,此时,我们也需要对源码进行修改。

优点: 可以根据自己的需求来修改源码,无需依赖于官方的发布版本,也可以更好地适应项目的需求,自由度相对更高

缺点: 需要自己维护这个AAR包,当React Native官方发布新版本时,需要自己手动同步源码,然后重新编译打包。
也可以采用字节码插桩的方式,直接在项目中引入React Native的源码,然后针对需要修改的地方进行修改,这样可以减少维护成本。

不管是需要修改源码还是针对低版本的React Native,自行编译源码都是很有必要的操作。
所以,个人还是推荐自行编译源码的方式,这样可以更好地适应项目的需求,也可以更好地理解React Native的构建过程。

处理 native module 的依赖

在Android中对于React Native中的Native Module而言,本质上就是一个Android Library Module,我们可以把Native
Module作为一个独立的模块引入到项目中。

这里也有两种做法

  1. 采用传统的方式,直接把Native Module作为一个独立的模块引入到项目中,也就是直接依赖源码。
  2. 自己编译Native Module,打出AAR包引入

关于源码依赖的方式,管理起来就相对复杂一些,为了方便的管理这些native module,可以针对package.json文件进行处理,把依赖的native
module中的android部分的代码安装到Android项目中。通过project的方式依赖进项目,这样相当于把native module作为一个独立的模块引入到项目中。

个人更加推荐自己编译Native Module,打出AAR包引入的方式,自己开发的Native Module不用说,本质上就是一个Android Library
Module,所以可以直接打出AAR传到maven私有仓库中通过远程依赖的方式实现。
对于三方的Native Module,也可以把源码拉下来自行编译,打出AAR通过远程依赖的方式引入到项目中。

处理 React Native 插件和脚本

上面也说到了,react-native-gradle-plugin 和 native_modules.gradle 这两个插件是可选的,他们的作用主要是帮助我们更好地管理React Native的构建过程,方便我们在项目中引入React Native的功能。

个人的建议是根据自身的需求,对插件和脚本进行定制化的来引入,也方便于App项目直接跟React Native源码联调时不至于依赖出问题。

如下示例:

在这里插入图片描述

相较于传统RN结构的模式,这种结构更加清晰,也更符合Android项目的组织方式。

同时,也可以方便的把RN进行组件化。对于已有项目来说,基本也没什么改动,是一个比较好的选择。

总结

到这里,RN的默认项目结构和构建的分析,以及对如何更加贴近日常开发的RN项目搭建的思考就结束了,希望能给到各位大佬一些帮助。


感谢阅读,觉有有帮助点赞支持,如果有任何疑问或建议,欢迎在评论区留言。如需转载,请注明出处:喻志强的博客 ,谢谢!

相关文章:

  • Git的使用记录+坑的处理
  • VTK9.2.0+Qt5.14.0 绘制点云
  • STM32F103 CubeMX 使用USB生成键盘设备
  • 蓝桥杯刷题(十四)
  • 分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)
  • 千益畅行 || 共享旅游卡推广运营怎么做?
  • YOLOv8融入低照度图像增强算法---传统算法篇
  • EtherCAT转RS232网关在风电领域的应用
  • 虹科Pico汽车示波器 | 免拆诊断案例 | 2018款东风风神AX7车发动机怠速抖动、加速无力
  • Q_STATIC_ASSERT_X作用
  • 一些常见的与 Vim 相关的文件类型及其描述
  • 服务器呀服务器,一个虚拟专用服务器的使用教程
  • hadoop基本概念
  • 影视类视频片段分割
  • node项目中express的使用
  • 深入了解以太坊
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • Android组件 - 收藏集 - 掘金
  • Cumulo 的 ClojureScript 模块已经成型
  • flutter的key在widget list的作用以及必要性
  • golang 发送GET和POST示例
  • in typeof instanceof ===这些运算符有什么作用
  • JavaScript设计模式与开发实践系列之策略模式
  • Java超时控制的实现
  • Laravel 实践之路: 数据库迁移与数据填充
  • Mithril.js 入门介绍
  • October CMS - 快速入门 9 Images And Galleries
  • Python爬虫--- 1.3 BS4库的解析器
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • ubuntu 下nginx安装 并支持https协议
  • v-if和v-for连用出现的问题
  • Vue2.0 实现互斥
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 翻译--Thinking in React
  • 分布式事物理论与实践
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • !!java web学习笔记(一到五)
  • $(selector).each()和$.each()的区别
  • (8)STL算法之替换
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (多级缓存)多级缓存
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (论文阅读40-45)图像描述1
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)scrum常见工具列表
  • (转)四层和七层负载均衡的区别
  • *p++,*(p++),*++p,(*p)++区别?
  • .bashrc在哪里,alias妙用
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net6 webapi log4net完整配置使用流程