调查可行的选择
[注意此答案包含原始问题中的发现]
我对各种选项进行了更多的调查,这里有一些初步的发现。
0.编译NodeJS
每个选项都使用为 Android 编译的某种形式的 NodeJS。但是要使用任何选项,您可能希望编译到不同的 Node、Android 和架构(x86、ARM、ARM64 等)版本。
这是有问题的。NodeJS 有一个android-configure
脚本,但这会在我尝试过的大多数组合中导致错误。我为一个工作构建脚本创建了许多 github 问题。在这个问题中收集了结果:
总结一下:
- 共享库构建全部失败(除非在您的 android 上进行物理构建,请参见下文)
- 带有 NodeJS (
libnode.a
) 的J2V8静态链接在libj2v8.so
7.x 之前的作品中7.9.0
- build-as-node-executable 适用于 7.x(使用dna2oslab构建脚本)
@mafintosh使用了一种有趣的解决方法:使用 Termux 将 Node 传输到设备并在那里进行编译(需要大量空间和时间,但有效)。
1. 运行包含NodeJS ( J2V8 ) 的V8 javascript 引擎
J2V8 是 V8 的一组 Java 绑定。J2V8 专注于性能以及与 V8 的紧密集成。[...] [which] 在 JS 和 Java 代码之间强制使用更静态的类型系统,但它也提高了性能,因为没有创建中间对象。[...]
构建 J2V8 需要构建原生部分和 Java 库(.jar/.aar 文件)。为了构建原生部分,我们首先将 node.js 构建为一个库,然后将 J2V8 静态链接到它。[...]
对于交叉编译,J2V8 使用 Docker(android、linux、windows)和 Vagrant(macos)。
参见幻灯片:在 Java 世界中运行NodeJS (或参见InfoQ 视频,32 分钟。)
特点:
- 用更强大的 v8 替换 JavaScriptCore 引擎(使用 NodeJS)
- 通过添加的 J2V8 JNI / Java 层支持多线程(线程/工人)
- 2-way js-to-java 桥(从脚本调用 java,反之亦然)
- 2路集成错误/异常处理
- 漂亮的交叉编译交互式构建系统(正在开发中)
- 铬调试支持
- 其他,类型化数组,ES6 支持,...
特点:
- 指定要编译的版本
build_system/build_settings.py
简单地开始构建python build.py --interactive
,选择构建:
[0] Docker >> android-x86 >> NODE_ENABLED
[1] Docker >> android-arm >> NODE_ENABLED
[2] Docker >> alpine-linux-x64 >> NODE_ENABLED
[3] Docker >> linux-x64 >> NODE_ENABLED
[4] Docker >> linux-x86 >> NODE_ENABLED
[5] Vagrant >> macosx-x64 >> NODE_ENABLED
[6] Vagrant >> macosx-x86 >> NODE_ENABLED
[7] Native >> windows-x64 >> NODE_ENABLED
[8] Docker >> windows-x64 >> NODE_ENABLED
[9] Vagrant >> windows-x64 >> NODE_ENABLED
选择构建步骤(或all
):
NodeJS --> CMake --> JNI --> Optimize --> Java/Android --> JUnit
将 V8 编译为共享库 libj2v8_{platform}_{abi}.{ext}
- 注意:
nodejs
构建步骤无法构建节点共享库(错误),创建静态libnode.a
链接libj2v8.so
- 有一个 JNI 层,使 Java 可以访问 v8 的大部分内容
- 在 Java 中实现的附加功能(例如 JS <--> Java 桥)
- 最终构建输出是一个 Gradle
.aar
,作为项目依赖项包含在内
优点:
- 比较活跃的项目
- 高质量的代码,包括 Java 单元测试
- 将 Java 的全部功能添加到您的应用程序设计工具包中
- 出色、直观的构建系统(完成后)
缺点:
- 很少,大多是过时的使用文档
- 特别未记录的是在大型(r)规模的 JS 项目中的使用
- 很多必须维护的JNI胶水代码
- 项目维护不善(许多旧的未解决问题,未合并的 PR)
- 比其他选项更难理解 J2V8 项目设置(许多文件)
- 许可问题(EPL 1.0 许可中的“保留所有权利”)
android 上的 Node 通过使用共享库在 android 应用程序中运行您的 Node.js 来工作。然后它捆绑了一个WebView
托管您的 UI 代码的文件。所有 UI 都只是经典的 html/css/js。
在节点应用程序中,您可以要求node-on-android
访问 WebView。您可以使用它来加载 .html 文件中的 html 页面WebView
。
根据node-on-android
创建者 ( @mafintosh ) 的说法,这比 J2V8 更容易也更好,因为它直接将 V8 编译为真实的东西。
特点:
- 构建成熟的 NodeJS 应用程序,包括 UI(通过本机 WebView)
特点:
- gradle
app
项目中的相关目录/文件:
app/src/main/include/node
带节.h
点头
app/src/main/jniLibs/arm64-v8a
与libc++_shared.so
和libnode.so
app/src/main/cpp
与native-lib.cpp
(包括node.h
)
- Java 代码,只是启动一个
Service
在单独线程中运行的节点
- 没有 JNI for
libnode.so
,因此private native void startNode(String... app);
在 IDE 中显示为错误(但可以编译)
- NodeJS 项目位于
android/app/src/main/assets/node
- NodeJS 代码被转移到临时存储并从那里执行
- NodeJS 应用程序通过公开的
loadUrl
函数
指定要在 WebView 中加载的视图
- 可通过 NPM 包访问节点服务
node-on-android
优点:
- 简单的项目,没有太多的管道代码
- 随附开箱即用的最新 v8.x Node 版本
- 简单的基于 HTML 的应用程序 UI 编程(例如使用choo)
- 开箱即用:)
缺点:
- 非常新的项目,仍然只有实验代码
- 仅用于
arm64
架构(计划提供完整的移动支持,或 DIY 构建)
- 没有可能的原生 UI(除非在 Gradle/Java/XML 中编码)
- Node 应用程序没有调试支持(AFAIK,但也许您可以以某种方式附加到 WebView)
3. 结合 React Native 和 NodeJS 应用即服务(react-native-node)
在后台运行一个真正的Node.js 进程,在 React Native 应用程序后面。
使用这个包,你可以:在 Android 中运行 http 服务器,使用 Node 流,与文件系统接口,从 React Native 中的 JS 线程卸载一些繁重的处理,等等!在 Android 中运行真正的 Node.js,您可以完成桌面上 Node.js 所能做的一切。
特点:
- UI 使用 React Native,NodeJS 作为后台服务
特点:
- 派生自NodeBase
- 与 node-on-android 非常相似(
Service
在单独的线程上使用 Node运行)
- 但
node
被编译/用作应用程序,而不是嵌入式共享库
- NodeJS 应用代码位于
{projectRoot}/background
- NodeJS 可执行文件在
/android/src/main/res/raw/bin_node_v710
- 在构建时,Node 应用程序被压缩,解压到 `/android/src/main/res/raw/{appName}
- 调用 NodeJS 服务就像从命令行运行一样,传递参数
- 节点服务
RNNode
通过导入在RN中可用react-native-node
react-native-node
还包含在构建时传输节点代码的 CLI
- Example 项目通过 REST 从 React Native 到 NodeJS 服务进行通信
- 在 Node 端运行
express
服务器http://localhost:5000
优点:
缺点:
- 非常新的项目,仍然只有实验代码
- 带有旧的 NodeJS
7.1.0
版本(但DIY 构建新版本)
- RN 和 Node 应用程序之间没有简单的通信方式(基于 REST)
- Node 应用程序不支持调试。真的很难知道发生了什么
现状 (2017-08-17)
我的目标是 React Native + NodeJS。这是我的活动状态:
- 将 NodeJS v7.x 版本编译为可执行文件
- 使用新的 J2V8 构建系统编译 NodeJS v7.4.0 到 v7.9.0
- 编译 NodeJS v8.1.2 很快就会与 J2v8 一起工作(编译针对
libc++
)
react-native-node
可以编译,但多次尝试后仍无法运行
node-on-android
有效,但仅节点应用程序开发和 64 位与 RN 不兼容
我决定合并react-native-node
是J2V8
因为:
React Native 0.46.4
+ NodeJS7.9.0
现在可以工作了!看:
我的用例:具有 P2P 去中心化网络的胖客户端
我正在考虑 CQRS(命令-查询-职责-隔离)设计:
- react-native UI 是从节点服务查询的视图构建的
- react-native UI 动作触发节点后台服务上的命令
- 后台服务处理网络消息、传入命令、触发事件
- 事件存储在 Realm DB 中,形成了前后之间的桥梁
详细信息:Realm.io 在 Android 胖客户端应用程序中桥接原生 NodeJS + React Native(CQRS 风格)
结论
即使多年来人们试图将 NodeJS 移植到 Android 上,仍然没有真正好的解决方案,它是开创性的。
在设置项目和构建环境时,您可能会遇到许多障碍和错误,但是一旦设置完毕,您就可以在手机上享受 Node 的全部功能。