在Android上运行NodeJS的可行选项(2017年8月)

Arn*_*ver 32 javascript java android node.js react-native

有许多旧的SO线程处理在Android上运行NodeJS.其中大多数不再可行(JXCore)和/或提供令人困惑,过时,不完整或错误的信息.

因此,我调查了目前(截至2017年8月)可行的方法,并找到了三个可能的候选人.

要在他们之间做出决定,我想知道:

  • 这些方法之间的主要区别
  • 每种方法的特定专业人员和骗局
  • 可能遇到障碍,挑战和缺点
  • 你知道其他可行的替代方案吗?

可行的方法是:

  1. 运行包含NodeJS(J2V8)的V8 javascript引擎
  2. 直接使用NodeJS,嵌入为本机库(node-on-android)
  3. 将React Native与NodeJS app-as-a-service(react-native-node)相结合

除此之外,我还找到了许多相关的有趣资源:

  • NPM在没有root的情况下直接使用Termux安装NodeJS(不适用于最终用户)
  • LiquidCore - 原生移动微应用程序devenv(未调查,有趣的概念)
  • dna2oslab - 有一个用于节点可执行文件的工作NodeJS构建脚本
  • 为Android构建NodeJS - 博客提供有用的编译技巧和示例项目

Arn*_*ver 15

调查可行的选择

[ 注意这个答案包含原始问题中的发现 ]

我已经对各种选项进行了更多调查,这里有一些初步调查结果.

0.编译NodeJS

每个选项都使用为Android编译的某种形式的NodeJS.但是要使用任何选项,您可能希望编译到不同的Node,Android和体系结构(x86,ARM,ARM64等)版本.

这是有问题的.NodeJS有一个android-configure脚本,但这会导致我尝试过的大多数组合出错.我为一个工作的构建脚本创建了许多github问题.在此问题中收集结果:

总结一下:

  • 共享库构建都失败(除了在你的android上物理构建时,见下文)
  • J2V8与NodeJS(libnode.a)静态链接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).

请参阅slideshare:在Java World中运行 NodeJS (或参见InfoQ视频,32 分钟)

特点:

  • 用更强大的v8替换JavaScriptCore引擎(使用NodeJS)
  • 通过添加的J2V8 JNI/Java层支持多线程(线程/工作者)
    • 每个线程都可以拥有自己的Isolated V8实例
  • 双向js-to-java桥(从脚本调用java,反之亦然)
  • 双向集成错误/异常处理
  • 漂亮的交叉编译交互式构建系统(正在开发中)
  • chrome调试支持
  • 其他,类型数组,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
    
    Run Code Online (Sandbox Code Playgroud)
  • 选择构建步骤(或all):

    NodeJS --> CMake --> JNI --> Optimize --> Java/Android --> JUnit
    
    Run Code Online (Sandbox Code Playgroud)
  • 将V8编译为共享库 libj2v8_{platform}_{abi}.{ext}

    • 注意:nodejs构建步骤无法构建节点共享库(错误),创建libnode.a要链接的静态libj2v8.so
  • 有一个JNI层可以使Java可以访问v8的大部分内容
  • 用Java实现的其他功能(例如JS < - > Java桥)
  • 最终构建输出是Gradle .aar,包含为项目依赖项

优点:

  • 相对活跃的项目
  • 高质量的代码,包括Java单元测试
  • 为您的应用设计工具包添加Java的全部功能
  • 优秀,直观的构建系统(一旦完成)

缺点:

  • 很少,大多数过时的使用文档
    • 特别是未记录的是在大型(r)规模的JS项目中的使用
  • 许多必须维护的JNI胶水代码
  • 项目维护不善(很多旧的未解决的问题,非合并的PR)
    • 一些PR已经流传了两年,甚至没有得到回应.不好
  • 比其他选项更难理解J2V8项目设置(许多文件)
  • 许可问题(EPL 1.0许可中的"保留所有权利")

2.直接使用NodeJS,嵌入为本机库(node-on-android)

Android上的节点通过使用共享库在Android应用程序内运行您的Node.js来工作.然后捆绑一个WebView托管您的UI代码.所有UI都只是经典的html/css/js.

在节点应用程序中,您可以要求node-on-android访问WebView.您可以使用它来加载html页面WebView.

根据node-on-android创建者(@mafintosh),它比J2V8更容易和更好,因为它直接编译V8 作为真实的东西.

特点:

  • 构建成熟的NodeJS应用程序,包括UI(通过本机WebView)

特点:

  • gradle app项目中的相关目录/文件:
    • app/src/main/include/node带节.h点头
    • app/src/main/jniLibs/arm64-v8alibc++_shared.solibnode.so
    • app/src/main/cppnative-lib.cpp(包括node.h)
    • Java代码,只是Service在一个单独的线程中运行一个节点
  • 没有JNI 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 app上没有调试支持(AFAIK,但也许你可以以某种方式附加到WebView)

3.将React Native与NodeJS app-as-a-service(react-native-node)相结合

在React Native应用程序后面的后台运行一个真正的 Node.js进程.

使用此软件包,您可以:在Android中运行http服务器,使用节点流,与文件系统接口,从React Native中的JS线程卸载一些繁重的处理,等等!在Android中运行真正的Node.js,您可以执行桌面上Node.js的所有操作.

特点:

  • 使用React Native作为UI,NodeJS作为后台服务

特点:

  • 源自NodeBase
  • 与node-on-android非常相似(Service在单独的线程上运行Node)
    • 但是node被编译/用作应用程序,而不是嵌入式共享库
    • NodeJS应用程序代码位于 {projectRoot}/background
    • NodeJS可执行文件在 /android/src/main/res/raw/bin_node_v710
    • 在构建时节点应用程序是tarballed,解压缩在`/ android/src/main/res/raw/{appName}
    • 调用NodeJS服务,就像从命令行运行一样,传递args
  • RNNodeRN导入节点服务react-native-node
    • react-native-node 还包含在构建时传输节点代码的CLI
  • Example项目通过REST从React Native传递到NodeJS服务
    • 在节点端运行express服务器http://localhost:5000

优点:

  • 简单的项目,没有太多的管道代码
  • 明显:在Android上用NodeJS反应原生支持!
  • Node-as-executable可能适用于64位设备+ react-native

缺点:

  • 非常新的项目,只有实验代码
  • 附带旧的NodeJS 7.1.0版本(但DIY构建新的版本)
  • RN和Node应用之间没有简单的通信方式(基于REST)
    • 需要扩展REST API或推出自己的机制
  • Node应用程序没有调试支持.真的很难知道发生了什么

现状(2017-08-17)

我的目标是React Native + NodeJS.这是我的活动状态:

  • 将NodeJS v7.x版本编译为可执行文件
  • 编译NodeJS v7.4.0至v7.9.0适用于新的J2V8构建系统
  • 编译NodeJS v8.1.2将很快与J2v8一起使用(编译反对libc++)
  • react-native-node 编译,但尽管尝试很多,但不会运行
  • node-on-android 工作,但仅限节点的应用程序开发和64位与RN不兼容

我决定结合react-native-node使用J2V8,因为:

React Native 0.46.4+ NodeJS 7.9.0现在正在运行!看到:


我的用例:胖客户端与P2P分散式网络

我正在考虑CQRS(命令查询 - 责任 - 隔离)设计:

  • react-native UI是从节点服务查询的视图构造的
  • react-native UI动作触发节点后台服务上的命令
  • 后台服务处理网络消息,传入命令,触发事件
  • 事件存储在Realm DB中,形成正面和背面之间的桥梁

详细信息:Realm.io将在Android胖客户端应用程序(CQRS样式)中桥接本机NodeJS + React Native


结论

即使在多年的人试图将NodeJS移植到Android之后,仍然没有真正好的解决方案,它是开创性的.

在设置项目和构建环境时会遇到许多障碍和错误,但一旦设置完毕,您就可以在手机上享受Node的全部功能.


Ale*_*lla 10

截至今天(2018年3月),还有另一个尚未列入当前答案的可行替代方案:Node.js for Mobile Apps.

该项目的核心是提供一个本地库,用于将Node.js嵌入到原生Android和iOS应用程序中; 但它也附带了React NativeCordova的插件.

该库的预构建二进制文件适用于Android armeabi-v7a,x86,arm64-v8a,x86_64和iOS 64位.

核心库是一个叉的NodeJS /节点chakracore,这又是叉的NodeJS /节点.Android版本是非常常规的Node.js构建为库,具有一些可移植性修复.iOS版本使用ChakraCore引擎而不是V8(由于nodejs/node-chakracore fork的更改,可以用ChakraCore替换V8).

React Native和Cordova插件可以更轻松地将Node.js添加到使用这些框架构建的应用程序中.Node.js代码运行在一个单独的引擎和线程中,而不是框架(React Native/Cordova).两个JavaScript世界之间的通信是通过插件提供的消息传递桥实现的.

项目网站上提供了更多信息,包括一些文档.

(完全披露:我为开发移动应用程序的Node.js的公司工作.)