首页 > 其他分享 >如何在原生鸿蒙中进行RN热加载

如何在原生鸿蒙中进行RN热加载

时间:2024-11-17 17:56:04浏览次数:1  
标签:鸿蒙 方式 bundle new 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中的日志系统,感兴趣的家人们可以点赞关注支持一下,方便后续第一时间能查看到我最新的分享。

标签:鸿蒙,方式,bundle,new,RN,加载
From: https://www.cnblogs.com/foodie/p/18550836

相关文章

  • 一分钟掌握 kom:一行代码,轻松玩转 Kubernetes 多集群管理!
    目录导读基于kom的Kubernetes多集群操作教程1.工具简介2.安装和运行2.1集成`kom`3.多集群管理3.1注册集群3.2查看和选择集群4.资源管理操作4.1查询资源4.2创建资源4.3更新资源4.4删除资源4.总结引用导读管理Kubernetes多集群通常是一项复......
  • 书生大模型实训营第4期基础岛第四关:InternLM + LlamaIndex RAG 实践
    书生大模型实训营第4期基础岛第四关:InternLM+LlamaIndexRAG实践1.什么是RAG?2.LlamaIndex+InternLMAPI实践2.1LlamaIndex的简单介绍2.2LlamaIndex+InternLMAPI实践2.2.1开发机环境配置2.2.2下载SentenceTransformer模型2.2.3下载NLTK相关资源2.3是......
  • 联邦学习开山之作Communication-Efficient Learning of Deep Networks from Decentral
    1介绍1.1背景越来越多的手机和平板电脑成为许多人的主要计算设备。这些设备上强大的传感器(包括摄像头、麦克风和GPS),加上它们经常被携带的事实,意味着它们可以访问前所未有的大量数据,其中大部分本质上是私人的。根据这些数据学习的模型持有承诺通过支持更智能的应用程序来大大提......
  • WPF ItemsControl.AlternationIndex AlternationCount
    <StyleTargetType="{x:TypeControl}"x:Key="lbxStyle"><Style.Triggers><TriggerProperty="ItemsControl.AlternationIndex"Value="0"><SetterProperty="Background&quo......
  • [Tricks-00004]CF1954F(自己胡的 trick,被 Burnside 完爆)
    介绍下自己的离奇思路:先读清楚题意!要求是旋转等价,即两个以\(c\)个\(1\)开头,总\(1\)个数不超过\(k+c\)的字符串算一种。那怎么刻画"只算一种"这个条件呢?一个想法可以是,对每个字符串赋一个权值,一种字符串的权值即旋转出来的每个合法的,把它们加起来应该是\(1\),再全部加出......
  • 三周精通FastAPI:42 手动运行服务器 - Uvicorn & Gunicorn with Uvicorn
    官方文档:ServerWorkers-GunicornwithUvicorn-FastAPI使用 fastapi运行命令¶可以直接使用fastapirun命令来启动FastAPI应用:fastapirunmain.py如创建openapi.py文件:fromfastapiimportFastAPIapp=FastAPI(openapi_url="/api/v1/openapi.json")@app.g......
  • npm | Yarn | pnpm Node.js包管理器比较与安装
    一、包管理器比较参考原文链接:2024Node.jsPackageManager指南:npm、Yarn、pnpm比较—2024Node.jsPackageManagerGuide:npm,Yarn,pnpmCompared(nodesource.com)以下是对Node.js的三个包管理工具npm、Yarn和pnpm的优缺点总结:npm(NodePackageManag......
  • Python--scikit-learn
    数据集sklearn.datasetsfromsklearn.datasetsimportload_iris,fetch_20newsgroups小数据集下载load_xxx大数据集下载fetch_xxx模型KNNK-近邻算法参考距离计算k值选择kd树fromsklearn.neighborsimportKNeighborsClassifierfromsklearn.neighborsimpor......
  • 【转载】遗传算法—HyperNEAT Explained——Advancing Neuroevolution
    原文地址:https://hunterheidenreich.com/posts/next-gen-neuroevolution-hyperneat/ExpandingNeuroEvolutionLastweek,IwroteanarticleaboutNEAT(NeuroEvolutionofAugmentingTopologies)andwediscussedalotofthecoolthingsthatsurroundedthealgori......
  • 鸿蒙NEXT开发教程:浅谈@ComponentV2装饰器
    听说今天的广州车展上有一部分人已经看到华为汽车的最后一“界”,尊界超豪华大轿车,应该很快就要正式亮相,可以期待一波。在api12之后,鸿蒙系统推出一个V2版本的状态管理装饰器,不过目前还在开发试用状态,幽蓝君仔细研究了一下,今天跟大家做一个简单的介绍。幽蓝君对V2版本装饰器的总结......