用于无头JS任务和服务的JS运行时
无头JS任务和服务在后台使用Vega应用组件。应用组件在顶部添加了辅助JS运行时(由Hermes提供支持),以启用JS代码执行并可让您侦听代码中的生命周期事件。无头JS任务和服务的每个实例都有自己的JavaScript运行时实例。无头JS上下文中支持的模块
为了保持较小的内存占用,无头运行时是可用用户界面的简化版本,仅支持下表中列出的模块。在无头JS上下文中支持的React Native库
由于无头JS运行时支持的模块有限,因此它仅支持有限的React Native库,如下表所示。导入指南
无头运行时对可以导入的内容有严格的限制。导入用户界面组件或不支持的库会导致崩溃。 下面列出了可安全导入内容和不能安全导入内容的示例。安全导入
✅ 标准React Native非用户界面实用工具:不安全的导入
❌ 用户界面组件(崩溃):Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DeviceInfo' could not be found”(不变量违规:TurboModuleRegistry.getEnforcing(…):找不到“DeviceInfo”)的错误,则您正在导入的用户界面组件或用户界面相关API在无头上下文中不可用。查看您的导入内容并查看本文的故障排除部分。
使用不受支持的模块
使用上面未列出的任何模块或库都会导致运行时错误,如下例所示。此错误指出DeviceInfo模块在无头JS上下文中不可用。
E Volta:[KeplerScript-JavaScript] Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DeviceInfo' could not be found. Verify that a module by this name is registered in the native binary., js engine: hermes.
即使您没有直接导入有问题的模块,也会出现这个错误。它发生在以下情况下:
- 您使用的一个模块导入了有问题的模块
- 您尝试使用不支持的库
- 您以不正确方式导入了模块
@amazon-devices/react-native-w3cmedia而不是使用其无头导出,就会看到这个错误。
@amazon-devices/react-native-w3cmedia的无头导出仅包括在无头JS中安全运行的模块。如果您跳过此导出,您的代码将尝试加载与用户界面相关的模块,这些模块依赖于不支持的功能,例如来自@amazon-devices/react-native-kepler的DeviceInfo,从而导致错误。
虽然我们计划添加在构建期间检测不支持的模块的工具,但目前,请确保您仅使用Vega批准用于无头JavaScript的模块。
构建无头JS任务和服务
要注册您的无头JS任务和服务,您需要执行以下操作:步骤1:在应用的清单 (manifest.toml) 中公开您的组件
清单文件中的变体
不同的无头JS任务和服务需要在manifest.toml文件中有不同的设置。例如:- EPG同步任务使用
"runtime-module = /com.amazon.kepler.headless.runtime.loader_2@IKeplerScript_2_0" - 无头JS播放使用
"runtime-module = /com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
- 无头JS播放的运行进程与您的用户界面相同
- EPG同步任务在单独的进程中运行
步骤2:注册入口点
要注册任务(使用doTask函数)和服务(使用onStartService和onStopService函数)的入口点,我们建议您创建两个单独的文件:task.js和service.js。将文件放在index.js旁边,后者使用AppRegistry.registerComponent注册用户界面的入口点。您可以使用task.js和service.js文件注册多个无头JS任务和服务的入口点。
- 用于无头任务的task.js
- 用于无头服务的service.js
- 用于任务的task.hermes.bundle
- 用于服务的service.hermes.bundle
react-native build-vega,则需要手动执行以下操作:
- 从您的入口点文件(
task.js和service.js)生成Hermes字节码Bundle - 自行将这些捆绑包添加到您的应用程序包 (VPKG)
调试无头JS任务和服务
日志记录
要在无头JS任务/服务中调试代码,您可以使用控制台日志 (console.log) 并在设备日志中查看它们。
从您的设备或模拟器shell运行以下命令:
无需重新构建即可快速更新JS Bundle
无头JS任务和服务现在可以获取更新后的JS Bundle,而无需重新构建和重新安装应用。 无头JS任务和服务不支持热重载或快速刷新,而通过这两个功能,无需重新启动即可显示更改。相反,您需要重新启动无头JS任务和服务才能拉取更新后的JS Bundle。 要使用此特性,请按照以下步骤操作。- 在调试模式下构建应用(用户界面和无头JS组件)。注意: 与用户界面组件一样,逐行调试不适用于发布构建。
- 安装应用。
-
从项目根目录运行Metro服务器 (
npm start)。 -
为应用和Metro经过配置而要使用的端口(通常为
8081)设置从您的设备(target)到开发计算机(host)的反向端口转发。如果不执行此步骤,该应用将无法连接到Metro服务器。 - 启动应用。您应该看到所有JS Bundle(包括用户界面和无头JS)现在都由Metro提供服务。
逐行调试
您可以逐行调试无头JS任务和服务,但有一些限制:- 仅适用于Vega Studio的开发工具
- 开发工具仅显示最近推出的JS组件
- 用户界面和服务一起运行
- 该服务最后启动,因此开发工具显示的是service.bundle
- 要改为调试用户界面,您必须:
- 首先使用vega device launch-app -a <无头JS组件名称>启动无头服务
- 然后启动用户界面组件。
- 开发工具现在显示index.bundle
- 在调试模式下构建应用(用户界面和无头JS组件)。注意: 与用户界面组件一样,逐行调试不适用于发布构建。
- 安装应用。
-
从项目根目录运行Metro服务器 (
npm start)。 -
为端口8081(或为您的应用和Metro配置的端口)设置从您的设备(
target)到开发计算机(host)的反向端口转发。如果不执行此步骤,该应用将不能连接到Metro服务器并与开发工具进行交互。 -
启动您要调试的无头JS任务或服务。
- 使用以下命令手动启动:vega device launch-app -a <无头JS组件名称>。
- 启动用户界面组件。
- 在Vega Studio中,打开命令面板并选择“Vega: Launch Dev Tools”。导航到“Sources”(源)选项卡并选择“React Native”。
-
验证列出的Bundle (
index.bundle/service.bundle/task.bundle) 是否是您要调试的Bundle,以及其源是否已加载。注意: 开发工具将显示有关无法加载源映射的错误 - 可以忽略该错误。 -
要设置断点,请搜索目标代码并单击要添加断点的行号。请注意,只有在设置断点后执行的代码才会命中断点。这意味着启动时立即执行的代码(例如无头JS任务的
doTask或服务的onStartService)中的断点不会被触发。对于这些情况,请继续使用日志进行调试。 - 关闭开发工具实例并在两次应用启动之间重新启动它,因为开发工具不会自动刷新。
崩溃报告
来自无头JS任务或服务的未处理JS错误将导致应用崩溃并生成汇总崩溃报告 (ACR)。目前,此行为仅适用于无头JS任务和服务的发布构建。对于无头JS任务和服务的调试构建,请继续使用设备日志来检测任何未处理的JS异常。无头JS任务和服务问题故障排除
我的无头JS任务/服务在调试模式下运行,但在发布模式下无法启动或出错
检查日志,如果您看到如下错误,则说明您的任务/服务Bundle正在尝试初始化或使用无头JS上下文不支持的模块。步骤1:使用react-native-bundle-visualizer来查看您的无头JS任务/服务包的构成
例如,比较task.bundle意外从@amazon-devices/react-native-kepler中提取了不受支持的模块时的构成。
场景2:错误导入
场景2中task.bundle的组成表明该Bundle中包含了来自@amazon-devices/react-native-kepler的许多模块,甚至包含那些在无头JS上下文中不支持的模块。确认任务/服务Bundle包含不受支持的模块后,请继续执行步骤2以确定是什么引入了这些模块。
步骤2:手动检查调试构建的task.bundle/service.bundle
打开服务/任务(以引发错误者为准)的JS Bundle(不是Hermes字节码Bundle)。您通常可以在build/lib/rn-bundles/Debug中找到它们。假设它是task.bundle。您可以使用任何您常用的编辑器将其打开。
例如,让我们以上面存在错误导入以及以下错误的task.bundle为例:
DeviceInfo作为输入的TurboModuleRegistry.getEnforcing调用。
一旦找到,就可以确定哪个模块拥有此代码。
例如,在上面的task.bundle中,它为:
@amazon-devices/react-native-kepler/Libraries/Utilities/NativeDeviceInfo.js。
下一步是找出是什么依赖这个模块。为此,您可以在task.bundle中搜索模块ID 247。
在上面的task.bundle中,有两个模块依赖于模块ID 247:
node_modules/@amazon-devices/react-native-kepler/index.js
task.js导入的

