我试图了解 React-Native 的开发过程,所以我找到了有关 Metro 的信息,然后我阅读/观看了这个 Metro 视频):
Metro 是 React Native 的开发平台,它通过以下方式做到这一点。 公开HTTP 服务器,以便客户端(在本例中为模拟器)可以 与它通信,它还公开一个Websocket 服务器,以便它可以 将更新推送到客户端。
文档讨论了在端口 8081 上运行的"React Native Packager"(根据视频现在称为 Metro),那么这就是我们键入 react-native run-android 时启动的 HTTP 服务器?
关于Websocket,我仍然需要阅读更多内容。
文档说我们在两个环境中运行我们的JavaScript代码,这取决于我们是否处于调试模式,我理解这一点。但是这篇文章让我有点困惑,说:
No. 4 你的代码不能在 Node.JS 上运行:你得到的 JavaScript 运行时是 ether JavaScriptCore(非调试)或 V8(调试)。甚至 虽然您可以使用 NPM 并且节点服务器在后台运行, 您的代码实际上并不在 Node.JS上运行。所以你将无法 使用 Node.JS 包。一个典型的例子是jsonwebtoken,它 使用 NodeJS 的加密模块。
然后,我读到了这样的东西:
React Native 使用 Node.js(一个 JavaScript 运行时)来构建你的 JavaScript 代码。
Node.js 是一个服务器端 JavaScript 运行时环境。反应 本机附带了一些为 Node.js 编写的工具。
Node.js是一个基于Chrome的JavaScript构建的开源平台。 运行;它提供了一种轻松构建快速、可扩展的方法 程序。Node.js 允许您在终端中运行 JavaScript,并有助于 创建模块。
在本文中,它说:
下载节点.js从 nodejs.org。这个 JavaScript 运行时给你 访问 npm,这是节点创建的便捷工具.js 可用于管理开源包的项目。确保 您下载了最新的 LTS(长期支持)版本 节点.js。此下载还包括一个开发服务器 称为 Metro 捆绑器,它在调试时提供实时更新。
所以:
- Node.js 在 RN 中的角色是只访问 npm 并管理包?Metro 是否包含在 Node.js 中?我错过/混淆了什么吗?谢谢。
在当今的环境中,您将编写四种类型的 JavaScript:
1)客户端浏览器JavaScript:
这就是当他们访问您的网页时发送到网络浏览器的内容,然后在客户端的浏览器中执行。由于您希望JS快速加载并在各种浏览器上运行,因此通常使用转译器将您编写的现代ESnext转换为具有更好支持的缩小版本。
2)客户端原生JavaScript:
大多数设备确实具有本机JS运行时,因此您可以使用Android/iOS/桌面应用程序发布JS文件,然后在那里启动它们。这些引擎还支持将 JavaScript 中的钩子添加到您的本机代码中,这就是 React Native 提供其 API 的方式。
3) 服务器端 NodeJS JavaScript:
NodeJS 是用于运行服务器的运行时。
4) 在 NodeJS 上运行的构建脚本:
您可以使用 JavaScript 生成 JavaScript 文件。这就是您捆绑 (1) 和 (2) 的文件的方式(也可能是 (3))。
现在metro
是一个服务器端构建脚本(在 NodeJS 上),您可以使用它来 a) 启动一个将 JS 作为网页提供服务的服务器(1 和 3),或者 b) 将您的 JS 捆绑在可以安装在设备上的本机应用程序中 (2)。
Node.js 在 RN 中的作用是只访问 npm 并管理包?
不。metro
本身就是一个包,然后你可以在 NodeJS 上运行。
对于遇到这种情况的任何人,这是我的 2 美分解释。我将尝试解释在调试和发布模式下捆绑和执行应用的步骤。
在开发/调试模式下
Metro bundler(运行在 Node.js 之上)捆绑了你所有的 JavaScript 代码:你编写的代码、应用的依赖项包中的代码以及 React Native 附带的代码。它将它们捆绑到一个大的 JS 文件中,然后在端口8081
上启动本地服务器,以便在请求时提供捆绑的文件。这几乎就是Node.JS的参与方式。
进一步说明:
现在,当您打开编译的调试应用程序(.apk
适用于Android或.ipa
适用于iOS)时,它会向本地metro服务器发出请求以获取捆绑的JS文件,以便JS解释器(打包到应用程序中的JavaScriptCore或Hermes)可以开始执行它。但你可能会问,作为编译应用程序一部分的本机代码(Java/Kotlin
或Obj-C/Swift
)会发生什么?
简单的答案是,这些本机代码不能由JS解释器执行,因此必须单独执行,但在同一应用程序中执行。这意味着JS必须单独执行,本机代码也必须单独执行,但都在同一个应用程序中。
幸运的是,线程允许这样的事情,它们允许您在主程序(进程)中运行多个子程序(线程,如果你愿意的话)。
因此,当您编译的 React Native 应用程序打开(作为一个进程)时,实际发生的是它从其中启动三个线程:
-
JS thread
这是执行捆绑的JavaScript的JavaScript解释器(从metro服务器发送)存在的地方 -
Shadow thread
这是您赋予元素的基于 flexbox 的样式和布局转换为本机平台(Android 或 iOS)可以理解的布局和样式的地方。这是由跨平台布局引擎Yoga完成的。 -
Main/UI/Native thread
这是执行所有本机Java/Kotlin
或Obj-C/Swift
代码的地方。在这里,从中访问本机平台API(例如相机),并呈现本机平台UI元素(例如Android的View
和iOS的UIView
)。正是从这个线程中生成了其他两个线程。
上面提到的三个线程之间的通信由 React Native Bridge 或 Turbo Native Modules 促进,这是一种新方法。
在生产/发布模式下(当您编译以发布到应用商店时)
一切都与开发/调试模式下相同,只是捆绑的 JavaScript 文件在编译应用程序时与您的应用程序(apk
或ipa
)一起打包为资产,而不是从 Metro 服务器加载。
因此,当您打开已编译的应用程序时,JS 捆绑包只是从应用程序的 assets 文件夹中加载到 JS 线程并执行。这也意味着不需要Metro或Node.js因为应用程序需要工作的所有内容都已经预编译到其中。