一、背景

在上一篇博客中,我分享了将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热加载的更多相关文章

  1. java的热部署和热加载

    ps:热部署和热加载其实是两个类似但不同的概念,之前理解不深,so,这篇文章重构了下. 一.热部署与热加载 在应用运行的时升级软件,无需重新启动的方式有两种,热部署和热加载. 对于Java应用程序来说 ...

  2. tomcat 热部署、热加载 精析

        1.前言 找了很多篇文章,没有一篇文章讲的清晰.明了,很多人只是会用,但不是能真正说明白,这年头找个懂理论的,真难! 2.热部署 原定义:tomcat处于运行状态时,能够监测webapps下的 ...

  3. IntelliJ IDEA 2017.3.2 热加载(Hot Swap)

    一.IntelliJ IDEA 自带热加载,修改代码后点击Ctrl + F9即可 缺点:1.Ctrl + F9只对当前类重新编译加载 2.只支持构造代码块的CRUD.方法体内代码修改.资源文件内容的修 ...

  4. 关于在Intellij IDEA工具中配置热加载问题

    第一步,创建一个maven项目,然后在pom.xml文件中添加依赖(上图内容). 第二步:来到intellij idea主页面,点击File->Settings->Build->co ...

  5. elasticsearch中ik词库配置远程热加载

    1. 修改 IKAnalyzer.cfg.xml 配置文件中的<entry key="remote_ext_dict">http://127.0.0.1/xxx.txt ...

  6. vagramt中同步文件,webpack不热加载

    这是一篇参考文章:https://webpack.js.org/guides/development-vagrant/ 在使用vue-cli+webpack构建的项目中,如何使用vagrant文件同步 ...

  7. 使用 .NET Core 3.0 的 AssemblyLoadContext 实现插件热加载

    一般情况下,一个 .NET 程序集加载到程序中以后,它的类型信息以及原生代码等数据会一直保留在内存中,.NET 运行时无法回收它们,如果我们要实现插件热加载 (例如 Razor 或 Aspx 模版的热 ...

  8. webpack 教程 那些事儿03-webpack两大精华插件,热加载

    本节主要讲述 webpack的两大经典开发调试插件,热插拔内存缓存机制 文章目录 1. html-webpack-plugin插件的使用 2. webpack-dev-middleware 插件登场 ...

  9. [Eclipse] - 集成JBoss7热加载和自动发布

    使用Eclipse + JBoss开发时,总是要重启项目或JBoss,烦人.下面方法可以很简单的实现Eclipse + JBoss热加载和自动发布. 我的环境是JBoss 7.1.1 Final 1) ...

  10. Eclipse tomcat插件禁用热加载

    Eclipse中的tomcat插件默认是开户了热加载,只要是修改了java文件一保存,tomcat自动编译.加载.发布,很吃内存. 关闭方法: 打开eclipse,找到server项: 双击打开,修改 ...

随机推荐

  1. 解决 Rust WebAssembly 启动 Web 程序报错

    当你艰难入门 Rust ,并满怀斗志准备投身 WebAssembly,第一课也许会先给你泼盆凉水. 跟随 <Rust 和 WebAssembly> 文档的指引,一路 install.cod ...

  2. 禁止 SSH 传递 locale 环境变量

    SSH 在连接远程机器时默认会传递一些环境变量,其中就包括你本机的 locale 变量.这会导致远程机器的 locale 配置变成和你本地主机一样.有时候我们不希望这种行为,我们可以通过修改 SSH ...

  3. 深入浅出Stream流

    Java 8的新特性之一就是流stream,配合同版本出现的 Lambda ,使得操作集合(Collection)提供了极大的便利. 案例引入 在JAVA中,涉及到对数组.Collection等集合类 ...

  4. SpringCloudAlibaba 主要组件与nacos 填坑记录

    SpringCloudAlibaba 主要功能 与 实现组件 (1)SpringCloudAlibaba 主要功能 与 实现组件 [功能与实现组件:] 服务限流降级: 基本说明: 默认支持 WebSe ...

  5. EF Core – JSON Column

    前言 SQL Server 支持 JSON, 以前写过一篇介绍 SQL Server – Work with JSON. 但 EF Core 一直没有支持. 直到 EF Core 7.0 才支持. 参 ...

  6. Naming Conversion & Case Style 命名规范

    前言 写代码有 2 个点很重要 第一是表达 (不要词不达意) 要达到这点, 就要多参考其它人如何表达. 第二是一致性 (一样的东西就用一样的写法) 要达到这点就要建立规范 以前的笔记 命名规范 nam ...

  7. C# – 10.0

    前言 之前写过 6.0, 7.0, 8.0, 9.0 总结. 10.0 也是有些好东西哦, 尤其是 pattern matching 的完善, 差不多是时候可以重构 if else switch 的写 ...

  8. 加入 Flutter Engage,Pick 您的专属 Dash 形象!

    Flutter Engage 活动精彩来袭 对 Flutter 团队的开发者们来说,交流的重要性不言而喻,和您一样,我们也希望开发者们能够在不同的情境下进行互动分享.于是我们为您准备了一场特别的线上活 ...

  9. 搜广推算法校招面试:BOSS直聘 推荐搜索系统工程师

      本文介绍2024届秋招中,BOSS直聘的推荐/搜索系统工程师岗位一面的面试基本情况.提问问题等.   2023年12月,赶在秋招的末尾,投递了BOSS直聘的推荐/搜索系统工程师岗位,并不清楚所在的 ...

  10. Android Linux EAS优化-schedtune

    SchedTune SchedTune是一项与CPU调频相关的性能提升技术,它实现为一个cgroup控制器. 这个控制器提供了一个名称为schedtune.boost的配置参数,运行时系统可以使用它来 ...