NodeJS app for end-user distribution - node.js

I'm looking for the proper way to distribute/deploy a node.js app that would run as a small webserver on the user's machine.
Is there a stub method or install script or a "install wizard" that would download all node_modules dependencies, download the latest nodejs binary, set up the environment, etc... or I have to distribute it bulk with everything packed? Is there any guide for that purpose?

Edited :
You could install node and npm, download your dependencies by running npm install in the command line (first declare them within your package.json) only then users can run your script. This is how you do development in Node.js, or deploy to a development server. See using npm. You could automate that with a shell script if that is what you are after.
However, when distributing programs to end-users that might not be the best approach. Linux users are used to a package (.deb for instance) and Windows users are used to an .exe or a setup wizard.
That is why I recommended the tools below. I also assumed you were targeting Windows as this is less of a problem is unix-like environments.
If you want a single file (.exe), pkg and nexe are made for that purpose. These Node.js tools are used by the developer to compile JavaScript code into a single executable binary that is convenient for end-users and Windows deployment. The resulting .exe file is very light and does not require node to be installed on the end-user’s computers.
Electron along with electron-packager can produce setup wizards, but it installs a lot of files even for the smallest program. Your program will include all of node and webkit, that is why it produces heavy installs.
NSIS can also create a setup wizard, it is simple and does common stuff well (copying files, running shell scripts).
Original answer:
Short answer is: not really.
You have to keep in mind that Javascript is and has always been interpreted, so until recently never compiled to binary as you might do with other languages. Some exploration has been going on, but essentially you won’t get a "good practice" answer.
The long answer is, maybe, for some limited use cases:
There is the fresh new pkg that does exactly this, and it looks promising.
There has been nexe for a while, it works great for some use cases (maybe yours). Native/compiled modules are still an issue however.
Electron might work for a full blown app with a significant user interface, but it is not light or compact.
You could always use browserify to concatenate and uglify all your code with the modules you use and then make an installer with something like NSIS to setup node and your script. Native modules would still be a problem however.

Related

How to compile node.js to binary release (with native modules)

Currently, I’m experimenting with building Node.js projects (different bundlers and other kinds of stuff). And I got a simple idea about bundling Node.js to a single binary for Linux, macOS, or Windows.
There are two packages nexe and pkg both of them don’t really support native .node modules that are used by packages like bcrypt or realm. Were you performing a similar compilation? I would be extremely happy to see some real-world examples (I could not find them on GitHub).
But... for what? It's more like an idea for fun what we're able to archive with Node.js. Even if it will be working (I get it working on cjs packages without native modules) example project with hello wold may have a size above 30MB.
One cool observation is that #vercel/ncc is able to compile my project into a single directory, but it also doesn’t work without node_modules (probably, I had no environment to test it)
Update V1: Building realm is impossible in such kinds of projects, the simplest solution is to not use realm in node apps because it will crash the binary build (it's because realm is using tons of other packages such as electron or react-native which doesn't work at all when it comes to desktop platforms.
My code is available at the following repository: https://github.com/keinsell/typecraft
After days of struggling with researching how pkg works and searching for potential alternatives, I've found caxa which were working for me in a good way, and on the road, I also got pkg working fine with (actually only tested on bcrypt) native modules. My core insights on using pkg for building Node.js binaries are:
Use matrix-builds on CI to build package ex. win package from windows host, mac from macos host etc.
Be sure to include native modules to assets (there you can use require() function in JavaScript (example below) or use pkg.assets object in package.json - I don't really get it but it's contained in my issue on vercel/pkg - vercel/pkg#1473
+ require('bcrypt/lib/binding/napi-v3/bcrypt_lib.node')
export async function main() { /* ... */ }
Some modules are still build-crashing, and the good example is realm but I'll still search for a way of building it and including it into node.js binary application. All of my progress on researching Node.js builds will be available on https://github.com/keinsell/typecraft and this StackOverflow answer will be updated over time and my new discoveries.
Read this resource with examples and you will be able to compile it to a binary release. Of course, nexe is necessary but with pty.js you can successfully compile it with all the native libraries. Have a look at the source: https://www.jedi.be/blog/2013/05/14/compiling-packaging-a-nodejs-project-as-a-single-binary/

Packaging Software Ideas

We have a migration tool to migrate the customers data between different applications. I am looking for ideas to make it very easy for the customer to use this tool. Right now they invoke shell scripts with some options and get the data dump, but I want to make this even more easier for the end customer. Tool is written in nodejs
pkg could be what you're looking for.
From the package description:
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.
Use Cases
Make a commercial version of your application without
sources
Make a demo/evaluation/trial version of your app without
sources
Instantly make executables for other platforms
(cross-compilation) Make some kind of self-extracting archive or
installer No need to install Node.js and npm to run the packaged
application No need to download hundreds of files via npm install to
deploy your application. Deploy it as a single file Put your assets
inside the executable to make it even more portable Test your app
against new Node.js version without installing it

How to bundle a third party binary with Electron?

I am still new to the electron ecosystem and desktop development in general but what I wish to do is to interface with a third party, open source application that comes bundled in with my software. First, I am unsure on what the package options to distribute should be. Is it customary to have two downloads, one for users that already have the third party binary installed, and another one that includes it? Also how do I go about actually packaging, and installing the binary? Should this be an option on my package.json? What kind of script should I execute? Are there any npm modules to facilitate this?
edit - is it possible to invoke npm from my main.js even though a user has not previously installed node? I know node is bundled with the electron package but is npm too?
-The binary in this case is PostgreSQL
There are a couple of options coming to my mind.
Bundle a 3rd party installer w/ your app. This is what I did recently. On the first run I check if the service that I need is installed / running and if not I call the 3rd party installer / start it. When the installer quits I simply app.relaunch() and start consumig it. Of course you'll need installers for each platform you plan to support. And you'll have to figure out ways to check if the software is installed (properly) for each platform.
Bundle binaries w/ you app. Of course you can bundle pretty much anything w/ your electron app. Again, you'll need binaries for each platform you plan to support. And of course they shouldn't be linked to anything that the default user doesn't have on his machine like SDKs and additional headers ...
Less comfy but you can alway add some start-up message or before-download massage telling the user that he needs software xy in order to run your application.
Derivate of 1/2: Download required stuff on demand. For your example this would mean checking the user's OS and arch and then just download the required installers or binaries if available. You could also build the stuff on the user's machine although this probably being the worst/biggest/most complex solution.
Then there's things like https://www.npmjs.com/package/pg - you should always check npm if someone already built what you need ;)
I'd recommend using the great electron-builder which makes bundling stuff w/ your app a piece of cake.
Feel free to comment if you need more intel.

Provide Node.JS webapp "key in hand"

I am building a simple Node.JS application for a client. The webapp should be easy to deploy on each server instance (which are RedHat EL 6.3), "key in hand".
What is the best way to package a Node.JS app? Basically, I need an "installer" or "package" to:
Install Node.JS
Install the dependencies (npm install)
Populate the application files (CSS, JS, HTML, etc.)
You should deliver a self-contained package. Please check out the great site The Twelve-Factor App, specifically the build, release, run section. There is a lot of hard-won wisdom from experienced operations engineers embodied in that site.
In your app's repo, write a script (shell, node, whatever) that can generate a distributable archive
RPM or tar archive are the 2 most sensible choices for you. tar is more portable and simpler. RPM would integrate nicely with an RPM-based distribution. I would recommend starting with tar if you have not done a lot of software packaging/management work. RPM is significantly more complex than tar.
The tar archive should embed the node.js files within it. This will make your app easy to install and avoid sharing a system-wide node install thus creating artificial coupling. If you go the RPM route, you can specify node as a dependency in your RPM spec file (but you probably shouldn't - see below).
The archive should embed all of the npm dependencies as well. Don't run npm install at package install time. Consider using the npm shrinkwrap tool to manage your dependencies during development, but at deployment time they should be pre-bundled and ready to run.
Specifically, these are bad ideas you should avoid:
Do not download anything from the Internet during installation. This is brittle, slow, and potentially can throw you bad surprises including security problems
Do not build artifacts at install time that can be built at build time. So ship pre-build CSS files, requirejs optimized files, pre-compiled binaries, etc.
As to whether your application RPM should list node.js as a dependency or embed node into the RPM, here are some points to consider.
Embed node.js into your RPM
Single .rpm file to distribute
Allows your application to tightly control the node version it uses. (see below)
Higher reliability. The fact is your app is probably coupled fairly tightly to at least the minor version of node.js you develop on (0.8.x for example) or even a patch release (>= 0.8.12 < 0.9 for example). It's best to allow node.js to decouple your app from the OS, but don't be fooled into thinking your app will work reliably on a different version of node.js without testing & adjustment. Most commonly these days there's just 1 app running on the OS, and the notion of sharing node between apps incorrectly values conservation of disk space over proper decoupling and operational independence of applications.
It's unclear whether there are any official/reliable pre-built RPMs out there in yumland that will "just work".
Specify node.js as a dependency of your PRM
Follows the general philosophy of OS package management (avoid duplication, conserve disk space, etc)
RPM provides capabilities beyond TAR around inventory management, uninstallation, upgrade, etc. Since you are asking this question, you are probably not ready to address these properly yet, so you might want to start with tar and once you have a solid understanding of that, consider RPM upgrade scripts, etc.
The "single file to distribute" nice point can quickly become untenable once your app starts using a database or 3, supporting daemons for email, log aggregators, etc.

Is there a way to compile node.js source files? [duplicate]

This question already has answers here:
Is it possible to create desktop applications with node.js? [duplicate]
(5 answers)
Closed 7 years ago.
Is there a way to compile a node.js application?
I maybe very late but you can use "nexe" module that compile nodejs + your script in one executable: https://github.com/crcn/nexe
EDIT 2021: Nexe's latest release is from 2017 and it appears that development has otherwise slowed, so the more-widely-used alternative from Vercel should also be considered these days: pkg
Node.js runs on top of the V8 Javascript engine, which itself optimizes performance by compiling javascript code into native code... so no reason really for compiling then, is there?
https://developers.google.com/v8/design#mach_code
EncloseJS.
You get a fully functional binary without sources.
Native modules also supported. (must be placed in the same folder)
JavaScript code is transformed into native code at compile-time using V8 internal compiler. Hence, your sources are not required to execute the binary, and they are not packaged.
Perfectly optimized native code can be generated only at run-time based on the client's machine. Without that info EncloseJS can generate only "unoptimized" code. It runs about 2x slower than NodeJS.
Also, node.js runtime code is put inside the executable (along with your code) to support node API for your application at run-time.
Use cases:
Make a commercial version of your application without sources.
Make a demo/evaluation/trial version of your app without sources.
Make some kind of self-extracting archive or installer.
Make a closed source GUI application using node-thrust.
No need to install node and npm to deploy the compiled application.
No need to download hundreds of files via npm install to deploy your application. Deploy it as a single independent file.
Put your assets inside the executable to make it even more portable.
Test your app against new node version without installing it.
There was an answer here: Secure distribution of NodeJS applications. Raynos said: V8 allows you to pre-compile JavaScript.
You can use the Closure compiler to compile your javascript.
You can also use CoffeeScript to compile your coffeescript to javascript.
What do you want to achieve with compiling?
The task of compiling arbitrary non-blocking JavaScript down to say, C sounds very daunting.
There really isn't that much speed to be gained by compiling to C or ASM. If you want speed gain offload computation to a C program through a sub process.
Now this may include more than you need (and may not even work for command line applications in a non-graphical environment, I don't know), but there is nw.js.
It's Blink (i.e. Chromium/Webkit) + io.js (i.e. Node.js).
You can use node-webkit-builder to build native executable binaries for Linux, OS X and Windows.
If you want a GUI, that's a huge plus. You can build one with web technologies.
If you don't, specify "node-main" in the package.json (and probably "window": {"show": false} although maybe it works to just have a node-main and not a main)
I haven't tried to use it in exactly this way, just throwing it out there as a possibility. I can say it's certainly not an ideal solution for non-graphical Node.js applications.
javascript does not not have a compiler like for example Java/C(You can compare it more to languages like PHP for example). If you want to write compiled code you should read the section about addons and learn C. Although this is rather complex and I don't think you need to do this but instead just write javascript.

Resources