如何在原生鸿蒙中进行RN热加载
一、背景
在上一篇博客中,我分享了将RN的bundle包在原生鸿蒙开发中进行使用。但是如果我们在实际的开发过程中,每次修改完代码都需要打包,然后重新运行原生项目的话效率就有点太低了。
原生鸿蒙支持RN的热加载,每次改完代码直接ctrl+s即可,改动后的代码会自动同步到手机上。除此之外,还支持同时调试RN多个项目。今天我想给大家分享一下,如何在鸿蒙中实现RN的热加载,以及分享其中的问题。
在原生加载端推荐大家使用RNAPP的方式,因为这会让热加载的配置更加简单,具体原因请见下文分享内容。
二、搭建Metro热加载环境
1、配置metro
在鸿蒙原生中,是使用metro来实现热加载功能的。所以我们在在项目的metro.config.js文件中配置harmony平台的Metro配置选项,将以下代码复制进入即可:
// metro.config.js
const { mergeConfig, getDefaultConfig } = require('@react-native/metro-config');
const {
createHarmonyMetroConfig,
} = require('react-native-harmony/metro.config');
/**
* Metro配置
* https://metrobundler.dev/docs/configuration
*
* @type {import("metro-config").ConfigT}
*/
const config = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true
},
}),
},
};
module.exports = mergeConfig(
getDefaultConfig(__dirname),
createHarmonyMetroConfig({
reactNativeHarmonyPackageName: 'react-native-harmony',
}),
config
);
2、创建一个新的,支持metro热加载的RNInstance。
如果你是使用RNAPP启动的RN框架,不需要特别的配置,因为RNAPP中已封装好相关环境。
如果你是使用的RNSurface,就需要创建一个RNComponentContext,并在context的devToolsController中增加如下的事件监听,并删除原有的RNInstance实例,重新启动一个新的RNInstance实例,即可启用热加载的功能:
this.ctx.devToolsController.eventEmitter.subscribe("RELOAD", async () => {
this.cleanUp();
ths.init();
})
3、原生代码中使用metro加载器
这一步也推荐大家使用RNAPP的方式进行Bundle的加载,具体操作可以看我上一篇的博客。
场景一、如果你是使用RNAPP启动的RN框架,则只需要将 new MetroJSBundleProvider() 传给 jsBundleProvider 属性即可:
RNApp({
...
// 方式1
// jsBundleProvider: new MetroJSBundleProvider()
jsBundleProvider: new TraceJSBundleProviderDecorator(
new AnyJSBundleProvider([
// 方式2
new MetroJSBundleProvider(),
]),
this.rnohCoreContext.logger),
})
场景二、不使用 RNAPP 的话,需要开发者自己去创建并管理 RNInstance,假设你已经拥有了一个 RNInstance 的实例 rnInstance,加载Metro服务的方法可参考如下代码:
rnInstance.runJSBundle(new MetroJSBundleProvider())
4、启动一个RN远程服务端
和RN安卓端一样,调试的时候要先启动一个RN的远程服务端。这一步在官方文档里也有具体描述,需要打开命令行,执行npm start和rport命令:
我这边实测下来,要先hdc rport tcp:8081 tcp:8081,然后再npm run start,跟文档的顺序有些出入。不加run,直接npm start也可以。
问题一、一直等待,RN服务器同步bundle未成功
执行完命令后,你会发现一直停留在这个页面:
这里要等待个10秒左右,如果命令行没反应,回到命令行那里按几下回车,按完就能看到加载进度了。如果等了10秒按了回车还是不行,你要检查一下手机数据线是否松动了。如果手机的连接也没问题,那么就需要杀死手机上的APP,然后重启,重启后再等个5秒左右。如果还是没出现加载bundle的提示,继续杀死APP重启,多来几次。加载中的状态展示如下:
到这里就等着就可以了,大概5秒钟后,会出现以下提示,代表bundle同步成功:
问题二、报错了,说是端口监听失败
当你输入hdc rport命令的时候,报错说是端口监听失败:
这个问题非常常见,说明你之前已经运行过hdc rport了,所以8081端口已被占用。这里有2种解决方案,使用其他端口,或者是重启手机即可。
问题三、运行项目的时候报错,操作不允许?
具体报错堆栈为:operation not permitted
相信你看到这个报错肯定一头雾水,我第一次看到的时候雾水比你还大。出现的场景是在你启动了RN服务端以后,再去studio里面点运行以后。具体原因我猜测是目前该手机已经连上了调试,再去运行native项目冲突了。
这个问题我目前的解决方法是,把RN服务端关闭即可。这也意味着我们在RN调试的时候,不能同时调试原生那边的代码,二者只能一个一个来。如果有更好的解决方案,也欢迎大家来分享一下。
三、如何同时调试多个RN项目
1、在RN服务端使用多个不同的端口来区分
第一个项目使用hdc rport tcp:8081 tcp:8081,然后npm run start -- --port=8081
第二个项目使用hdc rport tcp:8082 tcp:8082,然后npm run start -- --port=8082
这里需要注意的是,npm run start的时候需要后面带上具体端口号,要不然就会报以下错误:
2、在鸿蒙原生端使用不同端口号进行对应
前面说过加载Bundle是使用的new MetroJSBundleProvider()的方式,我们可以点进去看下这个方式的具体代码实现:
也就是说如果你2个项目都使用这种方式进行加载的话,那么最终将同时指向8081端口,造成RN服务器错乱的现象,具体的现象可能是这样子的:
你会发现第2个APP打开的时候会闪退,并且闪退的日志没在第一个命令行窗口里,而是跑到了第1个项目的窗口中了。这里有2种改法,改起来其实很简单:
改法一:使用fromServerIp的方式,传入电脑IP地址和端口号,这个端口号就是你启动RN服务端时候的那个,一定要一一对应才行。
改法二、直接传入bundle的全路径,其中就会带上具体的端口号,也是一样必须和RN服务端那边的端口号一一对应才行:
四、加载bundle的方式介绍
在鸿蒙原生这边可以使用多种方式去加载RN的bundle,Demo里面也都给了一个实例。注意这里AnyJSBundleProvider是一个数组,这就意味着可以同时设置多种加载方式,会自动获取目前已支持的方式。所以这里其实有一个小技巧,就是多个项目同时调试的时候,你可以多设置几个端口,以防止RN服务端关闭以后,端口仍然被占用的情况。我这边给大家分享一下我个人对于这些加载方式的看法,先看下Demo中的代码:
方式一:new MetroJSBundleProvider()
使用这种方式加载的话,会自动获取到你电脑的IP地址,然后端口号写死8081。这就意味着你只能有一个RN项目使用这个方式,不然就冲突了。
方式二:MetroJSBundleProvider.fromServerIp(ip, port)
这个方式写法相对来说比较简洁,同时可以灵活设置端口号,以达到同时热加载多个项目的目的。缺点就是每次你切换网络或者电脑,这里都需要重新设置一下IP,不是很方便。
方法三:new MetroJSBundleProvider(url)
这种方式也可以实现动态修改端口号的目的,而且由于不需要添加IP地址,这种方式将不会随着网络切换和电脑更换的变化而变化。个人觉得如果是在需要调试多个RN项目的情况下,首推这种方式。
方法四:new ResourceJSBundleProvider()
这种方式是在bundle包内置到assets下面的时候使用的,也就是说加载项目中固定的某个bundle。如果你们项目中没有实时更新功能的需求的话,就可以使用这种方式,直接将bundle内置到项目中进行上线。当然还有一种用法,就是将它作为一个backup,在网络不好没有拉取到远程bundle的时候,就使用这个项目中内置的包。
方法五:new FileJSBundleProvider(fileUrl)
这种方式一般用来线上使用了,可以从用户的手机本地拉取最新下载的bundle进行加载,从而使得功能迭代、Bug修复更加快速。
五、本文总结
本文中,我分享了如何在原生鸿蒙项目中进行RN热加载。同时也给出了我在此期间遇到过的问题,并且都给出了解决方案,还分享了如何进行多个RN项目同时调试。
其次,我对原生鸿蒙这边加载bundle的方式代码进行了简单的分析,希望能对大家有所帮助。对于文章中有异议的地方,也欢迎大家批评指正。
在下一篇中,我将分享鸿蒙RN中的日志系统,感兴趣的家人们可以点赞关注支持一下,方便后续第一时间能查看到我最新的分享。
如何在原生鸿蒙中进行RN热加载的更多相关文章
- java的热部署和热加载
ps:热部署和热加载其实是两个类似但不同的概念,之前理解不深,so,这篇文章重构了下. 一.热部署与热加载 在应用运行的时升级软件,无需重新启动的方式有两种,热部署和热加载. 对于Java应用程序来说 ...
- tomcat 热部署、热加载 精析
1.前言 找了很多篇文章,没有一篇文章讲的清晰.明了,很多人只是会用,但不是能真正说明白,这年头找个懂理论的,真难! 2.热部署 原定义:tomcat处于运行状态时,能够监测webapps下的 ...
- IntelliJ IDEA 2017.3.2 热加载(Hot Swap)
一.IntelliJ IDEA 自带热加载,修改代码后点击Ctrl + F9即可 缺点:1.Ctrl + F9只对当前类重新编译加载 2.只支持构造代码块的CRUD.方法体内代码修改.资源文件内容的修 ...
- 关于在Intellij IDEA工具中配置热加载问题
第一步,创建一个maven项目,然后在pom.xml文件中添加依赖(上图内容). 第二步:来到intellij idea主页面,点击File->Settings->Build->co ...
- elasticsearch中ik词库配置远程热加载
1. 修改 IKAnalyzer.cfg.xml 配置文件中的<entry key="remote_ext_dict">http://127.0.0.1/xxx.txt ...
- vagramt中同步文件,webpack不热加载
这是一篇参考文章:https://webpack.js.org/guides/development-vagrant/ 在使用vue-cli+webpack构建的项目中,如何使用vagrant文件同步 ...
- 使用 .NET Core 3.0 的 AssemblyLoadContext 实现插件热加载
一般情况下,一个 .NET 程序集加载到程序中以后,它的类型信息以及原生代码等数据会一直保留在内存中,.NET 运行时无法回收它们,如果我们要实现插件热加载 (例如 Razor 或 Aspx 模版的热 ...
- webpack 教程 那些事儿03-webpack两大精华插件,热加载
本节主要讲述 webpack的两大经典开发调试插件,热插拔内存缓存机制 文章目录 1. html-webpack-plugin插件的使用 2. webpack-dev-middleware 插件登场 ...
- [Eclipse] - 集成JBoss7热加载和自动发布
使用Eclipse + JBoss开发时,总是要重启项目或JBoss,烦人.下面方法可以很简单的实现Eclipse + JBoss热加载和自动发布. 我的环境是JBoss 7.1.1 Final 1) ...
- Eclipse tomcat插件禁用热加载
Eclipse中的tomcat插件默认是开户了热加载,只要是修改了java文件一保存,tomcat自动编译.加载.发布,很吃内存. 关闭方法: 打开eclipse,找到server项: 双击打开,修改 ...
随机推荐
- k8s Deployment与Service配置样例
一.Deployment apiVersion: apps/v1 kind: Deployment metadata: name: pie-algorithm-farmland-detection s ...
- C#/.NET/.NET Core优质学习资料,干货收藏!
前言 今天大姚给大家分享一些C#/.NET/.NET Core优质学习资料,希望可以帮助到有需要的小伙伴. 什么是 .NET? .NET 是一个免费的.跨平台的.开源开发人员平台,用于构建许多不同类型 ...
- 一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优.如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误.本次调优的代码是埋点系统中的报表分析功能,小公司,开发结 ...
- 【Azure Developer】上手 The Best AI Code "Cursor" : 仅仅7次对话,制作个人页面原型,效果让人惊叹!
AI Code 时代早已开启,自己才行动.上手一试,让人惊叹.借助这感叹的情绪,把今天操作Cursor的步骤记录下来,也分享给大家. 推荐大家上手一试,让你改变! 准备阶段 下载 Cursor(htt ...
- 中文关键字检索分析-导出到csv或者excel-多文件或文件夹-使用python和asyncio和pandas的dataframe
1.02版本 把原来的tab一个个拼接成文件输出,改成pandas的dataframe 使用asyncio库来使用协程,但是测试下来速度好像是差不多的.可能速度太快了,没能很好的测出来差异. 原来的最 ...
- 使用VSCode搭建UniApp + TS + Vue3 + Vite项目
uniapp是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.以及各种小程序.深受广大前端开发者的喜爱.uniapp官方也提供了自己的IDE工具HBui ...
- Angular 18+ 高级教程 – Angular Compiler (AKA ngc) Quick View
前言 在 Get Started 那一篇,我们提到过 Angular Compilation.这篇稍微给点具体画面,让大家感受一下. 但不会讲细节,对细节感兴趣的可以看这篇 Medium – How ...
- QT原理与源码分析之如何开发一个自定义的绘图设备和QT绘图引擎?
简介 本文将介绍如何自定义QT绘图设备类和如何自定义QT绘图引擎类. 目录 QT绘图设备抽象类QPaintDevice QT绘图引擎抽象类QPaintEngine 自定义绘图设备类 自定义绘图引擎类 ...
- 【翻译】实现 Blocked Floyd-Warshall 用于解决所有对最短路径问题 C# 实现
介绍 在之前的帖子中,我们实现了Floyd-Warshall(弗洛伊德-沃沙尔算法)(四种变体)以及路由重建算法.在这些帖子中,我们探讨了所有对最短路径问题的基本概念.内存中的数据表示.并行性.向量化 ...
- 【解题报告】P8477 「GLR-R3」春分
P8477 「GLR-R3」春分 题目看起来比较魔怔,考虑怎么搞一下. 首先,一个最简单的想法,每对溶液组都配一个板子,可以用 \(n^2\) 个板子解决,看得出来很不优啊,但是可以得到 Sub1 的 ...