React Native开发总结(二)
58车商通RN落地实践
引言
开发已经经历了几个阶段,从Native App 到 WebApp大火,再到苹果公司禁Web,又发展到了Hybrid的Web与原生共生。再到React Native,这种利用Js 转成原生的取中方案。
React Native 说到底还是调用Native原生,所以效率损耗的话很接近原生开发。所以目前很多App 都采用了RN开发,本文将就58车商通介绍下RN在其中的应用场景,以及发展阶段
RN开发背景
58车商通
58车商通是58体系下的为车商打造的一款工具类App,帮助车商高效的管理自己的车辆。
主要功能包括:
发布车源(核心功能)帮助车商快速发布车源,和主App 58同城起到相辅相成的作用。需求变化比较频繁,开始采用原生开发,但是无法满足需求的频繁变化,于是2017年改版为Hybrid。后续考虑改版为RN
库存管理(核心功能)帮助车商高效的管理自己的车辆,包括已经发布的,已经售出的,已经下架的,等等,以及定价,预警等相关功能。需求变化相对稳定。
客户管理(核心功能)帮助车商管理自己的客户,区分出客户的购买意向程度,以及后续沟通等等。变化频率相对稳定
营销推广(核心功能)帮助车商推广车辆,包括置顶,刷新服务等,变化频率相对较高
总结:58车商通是58集团二手车部门的一个重要的App产物,帮助车商方便管理自己的车源,随时发布,同步其他市场。而 RN 模块第一次尝试放在了车商通的每日任务模块。
为什么会选中每日任务模块
每日任务模块:用户每日登陆之后可以通过每日的任务来赚取积分。用于推广等功能等。
那我们为什么要用每日任务模块来做呢。
首先,每日任务模块体量较轻,入手起来相对比较简单
其次,线上有成熟的h5,如果出现严重问题的话,我们可以及时切换到线上h5进行补救
然后,每日任务模块虽然量轻,但是可以覆盖协议的大部分功能。
最后就是这个模块需求变化相对来说比较快,也可以检验热更新模块。
接下来我们来聊聊RN。
什么是RN?
其实关于RN的概念可能大家也比较清楚了,在这里我们简单的说一下。
React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,目前支持iOS和安卓两大平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用;
RN的目标是:高效跨平台的开发Native应用;
RN的宗旨是:一次学习,多个平台编写代码;
如下图:我们可以清楚的看到RN是构建在React和JSX的基础上的。
为什么使用RN?
- 移动设备环境比web设备复杂得多,导致Native开发成本高;
- 为寻求APP的开发效率、成本、体验之间的平衡,我们之前选择了Hybrid的开发方案,这样既能拥有高效的开发效率,又能快速更新迭代APP;
- 然而在webview中嵌入HTML页面存在一些性能和体验上的弱势;
这也为技术发展提出了一个新的挑战:如何将开发成本和用户体检做好更好的平衡呢?
基于此我们可以使用React Native来解决,对于前端开发来说,既然H5能够替代原生应用,为什么还要去使用别的技术,但是,实际上来说,H5应用在用户体验和性能上远远无法比拟原生应用的,RN的切入点就是兼顾开发效率和用户体验的;
RN特性:
提供了原生控件支持
使用RN可以使用底层原生控件,iOS可以使用UITabBar、UINavigationController等标准的iOS平台组件;在Android平台我们可以使用Drawer控件;这样,就让我们的App从使用上和视觉上拥有像原生App一样的体验
异步执行
所有的JavaScript逻辑与原生平台之间的所有操作都采用异步执行模式,原生模块使用额外线程
触屏处理
RN引入了一个类似于iOS上Responder Chain响应链事件处理机制的响应体系,并基于此为开发者提供了诸如TouchableHighlight等更高级的组件,实现了高性能的图层点击与接触处理
58车商通RN模块整体技术架构
车商通RN整体分为三个部分:
- 客户端:提供部分基础组件、提供交互协议、支持UI渲染展示页面
- 服务端:提供业务接口、提供项目bundle下载地址
- 热更新平台:提供项目bundle文件、支持更新、回滚
####58车商通客户端设计和开发
客户端整体框架如下:
3.1、入口组件
每个应用程序都有一个对应的入口文件,index.js是Android和iOS渲染前端UI的统一入口定义声明UI模块的moduleName:
import { AppRegistry } from "react-native";
import App from "./src/index"; //业务入口AppRegistry.registerComponent("Wuba***", () => App);
把当前APP的前端UI对象注册到AppRegistry组件中;
AppRegistry 是运行所有 React Native 应用程序的 JS 入口点
应用程序入口组件需要通过 AppRegistry.registerComponent 来注册它们自身
当注册完应用程序组件后,Native就会加载jsbundle文件并触发AppRegistry.runApplication运行应用
3.2、RN启动流程(以OC 为例)
- 创建RCTRootView
设置窗口的跟控制器的View,把注册的RN模块添加进去 - 创建RCTBridge
桥接对象,管理JS和OC交互 - 执行RCTBridge loadSource
加载前端js代码 - 执行RCTBridge initModulesWithDispatchGroup
创建OC模块表 - 执行RCTJSCExecutor injectJSONText
往JS中插入OC模块表 - 执行JS代码,回调OC,调用OC组件
- 完成UI渲染
3.3、RN通信机制
这部分内容,其实网上的资料比较多,而我们结合源码,和已经一些已经公开的知识点,简单跟大家分享一下。后续如果大家干兴趣,可以在单拿出一篇文章来分析讨论。下面我们来简单看下RN从JS 端开始调起原生方法的原理(以OC为例)
OC生成一张模块配置表,包含所有模块和模块里的方法,根据特定的标识宏(RCT_EXPORT_MODULE()),将可以暴露的方法暴露给JS。
OC-JS交互流程:(注:此图是网上的示意图,但是表达的意思很明确,所以借用一下)
- js调用OC模块暴露出来的方法
- 把调用方法分解为ModuleName、MethodName、arguments,在丢给MessageQueue处理
- 把js的callback函数缓存在MessageQueue的一个成员变量里面,同时生成一个CallbackID来代表callback;在通过保存在MessageQueue的模块配置表把ModuleName、MethodName转成ModuleID、MethodID
- 把ModuleID、MethodID、CallbackID和其他参数传给OC(JavaScriptCore)
- OC接到消息,通过模块配置表拿到对于的模块和方法
- RCTModuleMethod对js传过来的参数进行处理
- OC模块方法执行完,执行block回调
- 调用第6步中RCTModuleMethod生成的block
- block带着CallbackID和block传过来的参数去掉用js里的MessageQueue方法invokeCallbackAndReturnFlushedQueue
- MessageQueue通过CallbackID找到相应的js的callback方法
- 调用callback方法,并把OC带过来的参数一起传过去完成回调
以上就是通信交互整个流程,但是在实际业务开发中我们发现,RN提供的基础组件已经不能满足我们的业务开发,部分需要依赖native原生功能来实现比如:模块间的跳转、分享等,这就需要我们与native底层约定一些交互方法来满足各种各样的业务场景,基于此前端封装了一个中间交互的协议层
3.3、交互协议设计
协议层是native和前端对NativeModules进行了一些约定的封装和处理,方便业务使用。
目前前端协议层通过一下几种类型类集中封装的:
- RN跳转类
- 调起Native组件类 如:loading、toast等
- 调起native功能类 如:分享、埋点、定位等
协议约定:
native封装模块宏CST***Component到NativeModules下
在模块宏CST***Component下声明函数宏 CST–Handler
函数固定传参两个,第一个是协议交互的所有参数param(jsonString类型),第二个固定传入callback函数
参数param格式
param = { action, params }; 也是固定两个参数 action:唯一确定调起的native组件,都是以CST开头的 如:action = "CST***Web"表示RN跳转H5 params:协议交互参数,每个协议都有不同的参数,具体协议的参数和native约定 如: 跳转H5协议传参(具体参数根据业务来制定) let params = {url, //h5链接... };
回调函数
CST***Handler的第二个参数就是协议的回调函数,传入function类型 固定接收两个参数 (error, event) => {第一个参数error是一个错误对象(没有发生错误的时候为 null)第二个参数event是native返回给前端的具体回调数据(jsonString类型) }
根据以上规则 前端统一封装工业务方调用的API接口
3.4、RN页面开发
在上面我们大概了解了RN APP中的启动流程和交互方式,那么如何应用要我们的日常开发中能,下面来介绍一下前端的UI的开发。
3.4.1、本地开发流程
为保证RN版本的匹配,和一些代码规范的统一,在开发自己项目时需要克隆RN种子工程
在开发过程中需要使用到本地调试,下面我们以iOS端为例看看如何进行页面调试
3.4.2、本地调试
1、iOS模拟器启动页面:
2、启动Chrome浏览器调试:
command+D弹出模拟器工具类 选择选项Debug Js Remotely
3、浏览器自动打开链接http://localhost:8081/debugger-ui/
这时能在浏览器上查看所有前端js代码了
4、断点调试
打开目的js文件,找到要调试的函数,直接打断点,当执行该函数时就直接断点拦截了
服务端开发设计
服务端在整个RNAPP中承担的角色,就是为APP提供基本的数据接口服务和提供RN项目资源信息和下载地址;
此处就讲一下RN项目下载更新流程
服务端接口返回数据模型:
{"respData": {"h5Url": "","business": {"version": "90","remoteUrl": "https://***/10021_90_android_business.tgz"},"resource": {"version": "90","remoteUrl": "https://***/10021_90_android_assets.tgz"},"bundleId": "10021","unpacking": true,"downNow": false},"respCode": 0
}
服务端流程如下:
热更新平台设计
5.1、热更新流程
在传统的web开发中,我们修改完js之后在浏览器上就能直接看到效果,JavaScript本身就是一门动态语言,并不需要编译,浏览器每次刷新都拉取新的js文件;针对web应用最简单也最有效的优化就是缓存,当js没有更新,浏览器就不需要下载新的js文件;
在RN实现动态更新也是同样的思路,RN中前端JS代码最终都会打包成jsbundle文件,我们在需求更新时,在应用中从远程下载这个文件,并重新加载,就可以完成动态更新同时无需通过App Store重新发布;
APP RN资源更新流程:
1、APP启动时:
2、启动项目时:
所有前面的更新流程都会依赖于前端的RN资源,那么下面我们来看一下如何把一个项目在平台上录入、编译打包和上线的
5.2、平台资源录入
在项目开发完成,提交到公司Git代码仓库,就可以使用RN资源管理平台录入资源了;
平台功能如下:
项目录入:
在填写完信息后,平台会根据填写的git地址,把当前项目代码下载到服务器,并npm install安装当前项目需要的所有依赖;这个过程因为需要安装项目依赖,所以时间比较长,项目初始化完成就可以对项目编译打包了;
信息录入时,会为每个项目分配一个唯一的ID,也是客户端区分项目的唯一标识。
5.3、打包编译流程
RN项目编译打包流程
打包产物jsbundle
打包之后JSBundle文件的结构,基本分为3部分:
- 头部:全局定义,主要是define,require等全局模块的定义;
- 中间:模块定义,RN框架和业务的各个模块定义;
- 尾部:引擎初始化和入口函数执行;
在RN打包过程中,解析依赖关系,为每个模块添加一个id
1、需求
在实际的RN业务开发中,我们会涉及到很多个业务,这些业务基本上也不会耦合,这时我们就需要创建多个RN项目,每个项目编译打包成独立的bundle;
对于RN APP来说,即使只有一个helloworld页面,在使用官方命令react-native bundle打出来的jsbundle文件大约为530KB以上,RN依赖模块本身就占了99%以上;
如果更新的话,需要从网络上拉取整个包下载时间长,还会海鸥飞用户流量,每次进入RN页面还都要执行RN基础模块的定义;
在RN项目开发中基础库react和react-native是不变的,我们可以抽离这两个依赖打成common.bundle内置于APP中;
2、目标
- 抽离react和react-native打包成common.bundle
- 减小线上下发业务bundle体积,减少下载时间、节省用户流量
- 可预加载common.bundle,提升打开页面速度
3、分析
- 通过分析bundle结构和依赖查找,最终可以通过标记法进行分包
- 打包bundle时,根据entryFile进行深度遍历依赖分析,模块id不断递增,即越早引用的模块,id越小
- 在分析依赖时标记哪些模块属于common.bundle,哪些模块属于业务bundle
- 打包时先引入base.js保证common.bundle的模块id都在前面,先收集common.bundle的模块
- 在遍历进行依赖收集,输出业务bundle
//base.js
import React, { Component } from "react";
import {} from "react-native";
4、拆分打包流程
编译打包之后本地项目打包结果如下:
iOS端:
Android端:
5、总结
优点:
- 一次性打包输出common.bundle和业务bundle,效率高
- 用户只需下载业务bundle,减少流量消耗和下载时间
缺点:
- 直接引用react-native作为基础,common中可能会引入一些用不到的模块
总体上利大于弊,开发中也不可预知需要用到react-native哪些模块,直接打包一个全集也未尝不可。
6、展望
理论上我们还可以指定规则,解耦业务,根据不同的业务模块,划分出更多的bundle,每个bundle的模块id按照某个值开始,避免重复,类似android插件化处理资源id策略,按需加载业务bundle。
5.4、项目提测、上线
项目提测流程:
项目上线流程:
5.4、项目回滚
在日常开发中,纵然有多轮测试,也避免不了发布到线上不会存在问题,我们传统的解决方案就是定位问题,找出原因,解决完之后重新发布上线;如果是一个流量很大的需求,同时又出现了线上不容易解决的问题,此时线上就会出现长时间的功能无法使用的情况;这是我们就可以考虑到回滚,先把项目回滚到一个可用的版本,然后再来解决自己的问题。
RN项目回滚流程如下:
React Native开发总结(二)相关推荐
- 从 Android 到 React Native 开发(四、打包流程解析和发布为 Maven 库 )
1.从 Android 到 React Native 开发(一.入门) 2.从 Android 到 React Native 开发(二.通信与模块实现) 3.从 Android 到 React Nat ...
- React Native开发错误警告处理总结(已解决 !持续更新)
注:本文是我在开发过程中遇到问题解决方法的总结,之后会持续更新,希望帮助到更多的学习者.文中有不妥的地方希望指出共同学习,同时欢迎大神补充.(之后我会放出自己开发整理的笔记和GithubDemo地址, ...
- React Native开发之——Webstorm开发RN配置
前言 前文React Native开发之--Webstorm快捷开发介绍了使用Webstorm快捷开发React Native, 本文介绍Webstorm开发RN配置. Webstorm开发RN配置 ...
- 在windows上搭建React Native开发环境
最近要学习React Native,但是在window上搭建开发环境的时候遇到了些问题,以至于一直没有搭建好开发环境. React Native相关项目及文档: react-native的GitHub ...
- React Native开发(一)
本React Native讲解专题:主要讲解了React Native开发,由基础环境搭建配置入门,基础,进阶相关讲解. 关于React Native各种疑难杂症,问题深坑总结方案请点击查看: Mac ...
- React Native开发规范(非官方,自己定义的)
React Native开发规范 一.命名规范 二.代码格式 三.注释规约 四.样式规约 五.Redux 相关操作 六.桥接规约 七.JSX 规约 八.组件规约 九.npm 规约 十.性能优化 一.命 ...
- 【转】【React Native开发】
[React Native开发]React Native控件之ListView组件讲解以及最齐全实例(19) [React Native开发]React Native控件之Touchable*系列组 ...
- windows 下配置 react native 开发环境
windows 下配置 react native 开发环境 安装nvm 由于react native 需要使用 NodeJs 4.0以上版本,为了方便切换NodeJs,首先我们需要安装nvm. 你可以 ...
- React Native开发之必备React基础
为了帮助大家快速上手React Native开发,在这本节中将向大家介绍开发React Native所需要的一些React必备基础知识. 概述 本节课将从React的特点.如何使用React.JSX语 ...
- Windows环境下安装React Native开发环境----记一次填坑过程
前言 集成React Native开发环境遇到各个坑,调试了很久出现过找不到设备,百度上个别人的资料有误被绕来绕去耽误了很多时间,下载慢等待时间过长等问题,最后多方查阅资料,电脑重启等操作终于部署好了 ...
最新文章
- nowcoder119E A Simple Problem
- C#程序代码行号设置
- 拾遗:不用使 sizeof 获取数组大小
- 鼠标动效html,5种纯CSS3鼠标hover按钮动画效果
- Java程序员须知:分布式微服务为什么很难?
- How does JdkRegexpMethodPointcut work
- 长假首日全国热门景区出炉 西湖、天安门、广州塔位列前三
- 日志分析(shell脚本)
- 使用jQuery快速高效制作网页交互特效(1)
- 怎么维护 SQLite
- 【手写数字识别】基于matlab GUI知识库手写数字识别(写字板+图片)【含Matlab源码 1227期】
- oracle 创建表同时添加注释
- Java 3D期末复习第三章——Java 3D 基本图形功能
- 中子射线照相检测技术
- 东家冲~石池高速公路一阶段施工图设计--长沙理工大学继续教育学院自考道路毕业设计
- 流媒体/流媒体文件格式详解
- 6个让你10T硬盘立马爆掉的资源网站,再也不需要去百度上找资源了
- 《数字图像处理(第三版)》 第二章 数字图像基础 笔记1(视觉与电磁波谱)
- 吃鸡服务器维护7月5号,绝地求生7月5日维护到几点 7月5日吃鸡更新维护公告
- 案例 | 沃尔玛 x 腾讯云 Serverless 应用实践,全力保障消费者购物体验