There are a bunch of old SO threads dealing with running NodeJS on Android. Most of these are no longer viable (JXCore) and/or provide confusing, outdated, incomplete, or erroneous information.
Therefore I have investigated what seems to be currently (as of August 2017) viable approaches and found three likely candidates.
To decide between them I would like to know:
the primary differences between these approaches
specific pro's and con's on each approach
likely hurdles, challenges and shortcomings
do you know of other viable alternatives?
Viable approaches are:
Running V8 javascript engine which includes NodeJS (J2V8)
Use NodeJS directly, embedded as native library (node-on-android)
Combining React Native with NodeJS app-as-a-service (react-native-node)
Besides that I have found a number of related interesting resources:
NPM install NodeJS directly using Termux without rooting (not for end-users)
LiquidCore - native mobile micro-app devenv (not investigated, interesting concepts)
dna2oslab - has a working NodeJS build script for node executables
Building NodeJS for Android - blog with useful compilation tips and example project
Investigating viable options
[NOTE This answer contains findings that were in the original question]
I have investigated the various options a bit more and here are some preliminary findings.
0. Compiling NodeJS
Each of the options uses some form of NodeJS compiled for Android. But to use any option you would probably want to compile to different Node, Android and architecture (x86, ARM, ARM64, etc.) versions.
This is problematic. NodeJS has an android-configure script, but this results in errors in most combinations I've tried. I created a number of github issues for a working build script. In this issue results are collected:
Working build script for Android ARM Node 7.x or 8.x shared library
To summarize:
shared library builds all fail (except when building physically on your android, see below)
J2V8 with NodeJS (libnode.a) statically linked in libj2v8.so works for 7.x up to 7.9.0
build-as-node-executable works for 7.x (using dna2oslab build script)
One interesting workaround was used by #mafintosh: transfer Node to device using Termux and do the compilation there (needs much space and time, but works).
1. Running V8 javascript engine which includes NodeJS (J2V8)
J2V8 is a set of Java bindings for V8. J2V8 focuses on performance and tight integration with V8. [...] [which] forces a more static type system between the JS and Java code, but it also improves the performance since intermediate Objects are not created. [...]
Building J2V8 requires building both the native parts and the Java library (.jar/.aar file). To build the native parts we first build node.js as a library and then statically link J2V8 to that. [...]
For cross-compiling J2V8 uses Docker (android, linux, windows) and Vagrant (macos).
See slideshare: Running NodeJS in a Java World (or see InfoQ video, 32min.)
Features:
replace JavaScriptCore engine with more powerful v8 (with NodeJS)
multi-threading (threads/workers) support via added J2V8 JNI / Java layer
every thread can have its own Isolated V8 Instance
2-way js-to-java bridge (call java from script and vice versa)
2-way integrated error / exception handling
beautiful cross-compiling interactive build system (in the works)
chrome debugging support
others, typed arrays, ES6 support, ...
Characteristics:
Specify the versions to compile in build_system/build_settings.py
Start a build simply with python build.py --interactive, select build:
[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
Select build steps (or all):
NodeJS --> CMake --> JNI --> Optimize --> Java/Android --> JUnit
Compiles V8 as shared library libj2v8_{platform}_{abi}.{ext}
Note: nodejs build step cannot build Node shared library (errors), creates static libnode.a to be linked in libj2v8.so
Has a JNI layer to make large parts of v8 accessible by Java
Additional features (e.g. JS <--> Java bridge) implemented in Java
Final build output is a Gradle .aar to include as project dependency
Pros:
Relatively active project
Good quality code including Java unit tests
Adds full power of Java to your app design toolkit
Great, intuitive build system (once finished)
Cons:
Little, mostly outdated usage documentation
Especially undocumented is usage in large(r)-scale JS projects
Lot of JNI glue code that must be maintained
Project not well-maintained (many old open issues, non-merged PR's)
Some PR's hang around for 2 years without even getting a response. Not good
Harder to understand J2V8 project setup (many files) than other options
Licensing issue ("All rights reserved" in EPL 1.0 license)
2. Use NodeJS directly, embedded as native library (node-on-android)
Node on android works by running your Node.js inside the android app using a shared library. It then bundles a WebView that hosts your UI code. All UI is just classic html/css/js.
In the node app you can require node-on-android to get access to the WebView. You can use this to load an html page in the WebView.
According to node-on-android creator (#mafintosh) this is easier and better than J2V8 as it compiles V8 directly as the real thing.
Features:
Build full-fledged NodeJS applications, including UI (via native WebView)
Characteristics:
Relevant directories / files in gradle app project:
app/src/main/include/node with node .h headers
app/src/main/jniLibs/arm64-v8a with libc++_shared.so and libnode.so
app/src/main/cpp with native-lib.cpp (includes node.h)
Java code, just spins up a Service with node running in a separate thread
Has no JNI for libnode.so, so private native void startNode(String... app); shows as error in IDE (but compiles)
The NodeJS project resides in android/app/src/main/assets/node
NodeJS code is transferred to temporary storage and executed from there
NodeJS app specifies views to load in WebView via exposed loadUrl function
Node service accessible via NPM package node-on-android
Pros:
Simple project, not much plumbing code
Comes with a recent v8.x Node version out-of-the-box
Simple HTML-based app UI programming (e.g. using choo)
Works out-of-the-box :)
Cons:
Very new project, only experimental code still
Comes just for arm64 architecture (full mobile support planned, or DIY build)
Note: 64-bit cannot be combined with React Native (no 64-bit support)!
No native UI possible (unless coding in Gradle/Java/XML)
No debugging support on Node app (AFAIK, but maybe you can attach to the WebView somehow)
3. Combining React Native with NodeJS app-as-a-service (react-native-node)
Run a real Node.js process in the background, behind a React Native app.
Using this package you can: run http servers in Android, use Node streams, interface with the filesystem, offload some heavy processing out of the JS thread in React Native, and more! Running the real Node.js in Android, you can do everything that Node.js on desktop can.
Features:
Use React Native for the UI, NodeJS as a background service
Characteristics:
Derived from NodeBase
Very similar to node-on-android (run Service with Node on separate thread)
But node is compiled/used as application, not an embedded shared lib
NodeJS app code is located in {projectRoot}/background
NodeJS executable is in /android/src/main/res/raw/bin_node_v710
At build time Node app is tarballed, unpacked at `/android/src/main/res/raw/{appName}
NodeJS service is invoked as if run from the command-line, passing args
Node service RNNode is available in RN by importing react-native-node
react-native-node also contains CLI that transfers Node code at build time
The Example project communicates from React Native to NodeJS service via REST
Running an express server on http://localhost:5000 at Node side
Pros:
Simple project, not much plumbing code
Obvious: React Native support with NodeJS on android!
Node-as-executable will probably work with 64-bit devices + react-native
Cons:
Very new project, only experimental code still
Comes with old NodeJS 7.1.0 version (but DIY build newer ones)
No easy way to communicate between RN and Node apps (REST-based)
Need to extend REST API or roll your own mechanism
No debugging support on Node app. Really hard to know what's going on
Status (2017-08-17)
My goal is React Native + NodeJS. This is the status of my activities:
Compiling NodeJS v7.x versions as executable works
Compiling NodeJS v7.4.0 up to v7.9.0 works with new J2V8 build system
Compiling NodeJS v8.1.2 will soon work with J2v8 (compiled against libc++)
react-native-node does compile, but does not operate despite many tries
node-on-android works, but node-only app development and 64-bit incompatible with RN
I decided to combine react-native-node with J2V8 because of:
Great cross-compile build PR: https://github.com/eclipsesource/J2V8/pull/327
Builds into a nice J2V8 .aar to be easily included in Gradle
React Native 0.46.4 + NodeJS 7.9.0 is now working! See:
https://github.com/staltz/react-native-node/issues/5#issuecomment-323049897
My use case: fat client with P2P decentralized networking
I am thinking of a CQRS (command-query-responsibility-segregation) design:
react-native UI is constructed from view queried from the node service
react-native UI actions trigger commands on the node background service
background service processes network messages, incoming commands, triggers events
events are stored in Realm DB that forms the bridge between front and back
Details: Realm.io to bridge native NodeJS + React Native in Android fat client app (CQRS-style)
Conclusion
Even after years of people trying to port NodeJS to Android there are still no real good solutions, it is pioneering.
Expect many hurdles and errors as you set up your project and build environment, but once setup you could enjoy the full power of Node on your phone.
As of today (March 2018), there is another viable alternative not yet listed in the current answers: Node.js for Mobile Apps.
At its core, the project provides a native library for embedding Node.js into native Android and iOS applications; but it also comes with plugins for React Native and Cordova.
Pre-built binaries for the library are available for Android armeabi-v7a, x86, arm64-v8a, x86_64, and for iOS 64-bit.
The core library is a fork of nodejs/node-chakracore, which in turn is fork of nodejs/node. The Android version is pretty much regular Node.js built as a library, with a few portability fixes. The iOS version uses the ChakraCore engine instead of V8 (replacing V8 with ChakraCore is possible thanks to the changes in the nodejs/node-chakracore fork).
The React Native and Cordova plugins make it easier to add Node.js to applications built using those frameworks. The Node.js code runs in a separate engine and thread than the framework's (React Native / Cordova). Communication between the two JavaScript worlds is achieved via a messaging bridge provided by the plugins.
More information, including some documentation, is available on the project website.
(Full disclosure: I work for the company that develops Node.js for Mobile Apps.)
I am the author of LiquidCore. LiquidCore allows you to use full implementations of Node.js on both Android and iOS (iOS support was just released in version 0.5.0 -- September 2018).
LiquidCore is designed to enable multiple instances of Node to run simultaneously inside of a native mobile app. Each instance has its own virtual file system and native support for MySQL. The goal of the project is to enable full "micro apps" to be built using JavaScript/WebAssembly that can then be embedded into other apps, and I am still working toward that goal. But as of today, it works great if you just want a Node.js playground.
If you want to see what it can do, there is a simple node console app included for both Android and iOS.
I received an answer from #dna2github, the creator of NodeBase (thanks a lot!) that I'll include here (with permission):
Hi,
Thx for your question. I will do a brief answer in my view.
1. Running V8 javascript engine on android which includes NodeJS
pros:
integrated with Java world; can get full control of code.
cons:
a little hard to integrate with 3rd packages (need time to learn how).
need to learn about NodeJS and V8 things and also J2V8 docs (it consume long time).
2. Compile NodeJS as a native library (using node-on-android)
pros:
focus on js dev and no need to consider android side.
less learning time; similar to Cordova phonegap ....
cons:
js app => apk is a black box.
3. Running NodeJS on Android using Termux
pros:
flexible
cons:
no gui
4. Other interesting approaches
Not familar with LiquidCore; build micro service especially from url, I think, is to resolve no direct available storage on iOS. react-native-node the Android part is based on NodeBase method and use the prebuilt binary.
For NodeBase:
pros:
similar to 3; difference is that it has its own gui to start/stop app.
it can be a template for everything; for example, if would like to run django, you just need to replace node to python; rails, ruby...
cons:
native process access problem; the process cannot inherit access from Android app.
happy toy happy open source not like a commercial app; need more design if want to distribute to customers
At first, I run node in terminal; I find only dev can easily to use it to start js app. My friends and families also wanna some tools for example make water mark on picture in batch. NodeBase is created for them to easy to start/stop app. Then they just need to open browser to use it.
My another idea to create NodeBase is that we can build sharable applications that can be shared in the same Wi-Fi. When host starts an app, it can be visited by near people. Then they can work and play together. For example, we play werewolf and when there is no judge, we will start the werewolf app to have a judge for the first round. We can also share files between devices via download/upload.
For me, I can build what I want flexibly for example, I would like to make my Android as a machine learning runner; it can help me run machine learning programs at anytime (with node and python, thus in my another repo: dna2oslab is focus on building binaries) to make use of phone running time.
For you, if wanna port your app in a short time, I recommend 2; if you have time and other resources, 1 is better. 3 if you just make a toy/demo. 4 other is always possible and just do your imagination to create works.
Best wishes,
Seven
I tried using J2V8 in my Android Java app to run a JS script via node.js. It fails with this error:
java.lang.UnsupportedOperationException: StartNodeJS Not Supported.
The response from J2V8 was:
"The node wrappers are not available on Android, they are only available on the Desktop platforms (windows, mac, linux). This is the expected behaviour until we have node binaries for Android."
As far as I know, there are no current plans to implement node wrappers for Android.
Thanks,
Alex Donnini
Related
What are those reasons that people install Node.js on PC, and can a Node.js website be developed without installing Node.js on PC, if yes, what are the disadvantages?
Thanks
There can be many reasons, but some common ones:
When developing for any language, you'll need to be able to run and test your code, and running it locally makes it easier to do so.
Additionally, although you can use remote debugging, debugging is faster and easier to set up locally.
Many of the tools used by web developers are also developed in JavaScript and to run those locally, an engine capable of doing so is required. It makes sense that these tools are developed in JavaScript, not just because their primary user group will be able to understand and extend their code, but also because many of these tools need to be able to perform tasks and integrate with components that require something like a JavaScript engine to begin with.
In many situations, running a local environment on your development system will be cheaper and easier to maintain than having a separate test server; and you don't want to run your untested code on a production server.
Not directly related, but npm and Node.js have many uses beyond serving as a back-end to JavaScript-driven websites. Many people that have Node.js installed have nothing to do with web development, but have it for one of the many other reasons.
To answer your 2nd question: "can a Node.js website be developed without installing Node.js on PC?" Yes, but I can see very little reason to want to do so, unless you must. The advantage might be that you can avoid having a complicated piece of software with a large footprint and possibly some security concerns on your development machine. But the disadvantages for the average developer likely far outweigh that - more so if you just sandbox the entire development environment in case security is your main concern.
If you are writing everything from scratch, you don't need a package manager, but there is so much great stuff out there that you can use rather than writing it yourself! If you want to use it, you need a package manager that allows you to download (an optionally specific version of) specific packages, which may use packages themselves, and YOUR source code repository doesn't need to store a copy of every package you use, and every package used by the packages you use, because, as long as your source code specifies which packages it uses in a way your package manager understands, all you need to do is specify a manifest of (an optionally specific version of) specific packages your code uses directly.
"NPM" is one such package manager. "bower" is another but that uses NPM under the hood. Maven is a package manager I've seen in Java projects, and NuGet for MS projects, but for JavaScript projects it's usually NPM. And NPM uses node.
I have built a web automation programme with selemium & javascript. Now i want make it usable for everyone so that anyone can use it without any dependecies or coding environment i mean any non technical people can use it easily.
how can i do it?
One option is to use: https://www.npmjs.com/package/pkg
This command line interface enables you to package your Node.js
project into an executable that can be run even on devices without
Node.js installed.
The most useful part will be dependencies:
During packaging process pkg parses your sources, detects calls to
require, traverses the dependencies of your project and includes them
into executable
However, i expect this will not manage the webdriver executable. You'll most likely need to ship chromedriver/geckodriver/etc with your resultant exe.
Looking forward, i expect you'll need to manage your distributable for the rollout of new browser versions. Different users will be on different versions at different times and your relevant drivers will need to be updated and re-shipped.
I am trying to make my web application into a desktop app. I have already built and configured a server to host the backend scripting written in python.
My front end is written in JS, JQuery, HTML, CSS.
I have found an open source framework called Electron that packages web apps into desktop apps. Can I implement this so that it only wraps around my front end components without having to alter my back end server?
In essence, yes you can use your current web code to create a desktop app using Electron, as Electron in essence is basically just a simplified browser. However, you will need to add some things to your project if they don't already exist in order for Electron to work.
3 things in particular:
(See the quick start guide: https://electron.atom.io/docs/tutorial/quick-start/)
package.json
main.js
index.html
You'll also need nodejs installed as electron itself is an npm module.
So not quite as straightforward as you may have thought but definitely a fairly simple and viable approach.
I'm totally new to vert.x and I'm trying to see if it's possible to bring up an existing nodejs application in vert.x. Following the instructions at http://vertx.io/blog/vert-x3-says-hello-to-npm-users/, I used npm to install vert.x. I can run a simple hello-world app, but running our existing app is proving to be a little challenging. All the vert.x docs I've found talk about writing new apps, not porting existing code.
Oh, and the same code base needs to continue running on existing nodejs systems.
The trouble that I'm seeing is that vert.x won't load nodejs native modules correctly. For example, Vert.x choked on this require:
var fs = require("fs");
After a little searching I found the vert.x equivalent:
var fs = require("vertx-js/file_system");
Perhaps we could create an shim/abstraction layer to wrap the differences. I did a quick one for the file system API and it seems to load correctly. It does seem like writing an entire abstraction layer will be a fair bit of work. But it seems like it would solve the compatibility issue for APIs used within our source.
The real trouble is how to intercept all the require statements in the node_modules directories. Those modules are also going to be requiring lots of other native APIs like the file-system. This seems like a problem that others may have encountered and solved already. Better not to re-invent the wheel.
I could roll my own solution. I don't really want to sed/replace the node_module source except as a last resort. The only other alternative I have thought of is creating a directory of abstractions an inserting that directory name at the head of the NODE_PATH. This solution seems like it might work, but as I mentioned I'm a vert.x noob so I cannot forsee what kinds of pitfalls lie along that approach.
Does vert.x support a shim layer for running nodejs applications?
Short version TLDR:
You can't!
Long version:
Vert.x is not a Node.JS replacement or runtime. Although there are quite similarities and common design choices such as support for CommonJS modules and support for NPM the native libraries are not present. All I/O operations in Vert.x are done using Vert.x API and they do not always relate to the Node counter parts.
Also you should be aware that the JavaScript language version is not the same either, for example Node relies on V8 which nowadays is quite close to fully support ECMA2015 or ES6 for short, Vert.x as a framework running on the JVM relies on Nashorn (the JavaScript runtime from the JDK itself) which is still on ES5.
The idea of supporting NPM in Vert.x was not to emulate Node but to allow the usage of many of its modules (that do not depend on node native modules). For that reason there is a warning on the documentation. But I guess it is not clear.
There are some ways to get most out of NPM and Vert.x, one option is to go 100% ES6 and use a transpiler such as Babel to transpile back to ES5 which will run fine both with Node and Vert.x (until the moment you use a native module).
If you must to use Node, say that you already have an application built on node and the port is not worth (in terms of resouces/time/etc) then I'd suggest to look into the tcp eventbus bridge. This bridge will allow your existing application to produce and consume messages of an existing cluster of vert.x applications.
Can anybody explain me what is the real difference between these commands and what they specifically do:
cordova build
cordova run
cordova compile
cordova prepare
Reading from the doc doesn't help much https://cordova.apache.org/docs/en/4.0.0/guide/cli/#link-5
I have doubts because, for example, the command build and the command run both seems to build the app...
The order should be prepare -> compile -> build -> run. You can read in reverse second time to understand it better.
cordova run
- If you have already build the app, it simply runs. if you have not built the app then cordova will first build it and then run it. You cannot run a native app if it is not built (unlike web apps in browser).
cordova build
- Before you run you must build. As cordova supports multiple platforms you may specify iOS as target for the build phase. during build phase the necessary packaging is done for the targeted platform.
cordova compile
- A compile command is meant to check if your written code is perfect and no syntax error (or a reference error) exists.
cordova prepare
- A prepare is the phase before compilation. As cordova need to first convert your code to target the specific (iOS/android) platform, sometime a few developers optimize their code by first writing the code which is common for all platforms and then choosing prepare and writing platform specific code for iOS or Android for their ease. This step is also done in a situation when you do not find a good solution in cordova and want to write your own code to glue natively in platform.
Cordova has two separate phases in it's build process, Prepare and Compile.
Prepare basically copies the www folder into the platform specified, and any additional platform steps needed.
Compile will compile the app into a binary, (apk for android, .app for ios, etc)
The other commands are simply shortcuts for joining commands. The reason it is split out so much is so you can make hooks into before/after each step, if you need to run any custom code.
Build will run the the Prepare and Compile steps for you, since this is the most common usecase.
Run will call build before installing the finished app (and launching the emulator if --device wasn't specified). Looking at their docs I just learned you can run --nobuild to skip the build step!
Reading their docs was actually really helpful, so I would recommend doing that as well. https://cordova.apache.org/docs/en/latest/reference/cordova-cli/index.htm