JavaScript Executables
By: Corey Butler
Tags: Javascript Tips, JavaScript, Nodejs, Javascript Development, Web Development

Love it or hate it, JavaScript has become a prominent language beyond the browser. Node.js popularized the use of JavaScript development on the backend. The global JS community took it significantly further, leveraging Node and npm as a form of DevOps and code distribution. The next major wave, in my humble opinion, is greater emphasis on the use of JavaScript to produce executables.

What is a JS Executable?

A JavaScript executable is just a program written in JavaScript, then compiled to a runnable file. In other words, a .exe or .bin file (or no extension on macOS).

It has been possible to create executables for Node.js applications using community projects like node-windows/mac/linux, pkg, or nexe for a while, so the concept isn’t entirely new. These are all efforts maintained by the community (userland). While these types of efforts haven’t gone unrecognized, it’s always been more of an “add-on” experience.

Compiling With Deno 1.6.0

Deno 1.6.0 is/was scheduled for release on December 8th, 2020. It is notable for the inclusion of deno compile , a highly requested new feature for generating executables from your source code. While this is just the first release of several strategies, it marks an important milestone for the project. Deno is the first JavaScript runtime to support the creation of user-defined executables. This greatly reduces the amount of effort and third party tooling required to create executables.

The Impact of Executables

Currently, running JavaScript outside of a browser requires Node.js or Deno to be installed/available on the server/computer where the scripts will run. Executables are self-contained, so nothing needs to be installed beforehand.

This has particularly important ramifications for the creation of developer tooling and commercial software. Being able to ship a single executable can be a much simpler process than requiring users to have software pre-installed.

Consider the use case for Docker and containers. Containerization is a solid approach to development, but it still requires a runtime like Docker, podman, etc. That is a manageable hurdle for IT departments installing software on their servers, but it’s far more challenging for developers who ship software to individuals working on a workstation. It’s difficult to ship that great new FinTech app to your users if they also need Node or Docker installed to use it.

Fenix Web Server

Developing Applications as Executables

Some developers use tools like Electron for building applications with JavaScript. I’ve always liked Electron (built Fenix Web Server on it), but it isn’t a fit for every type of application. For example, many applications run as background services and do not need a dedicated UI. For these types of applications, Electron’s inclusion of a UI rendering system adds significant size to the application without adding additional value.

For applications like these, an executable is a slimmer and more manageable way to deliver software.

NVM for Windows

Developing CLI Applications

CLI (Command Line Interpreter) applications are a natural fit for the executable format. These types of applications are one of the purest forms of function, meaning they do something very specific.

With Deno 1.6.0, developers can create their own tooling without worrying much about runtime dependencies. Remember, executables are self-contained, so it does not matter if the runtime changes. For example, updating to a new version of Node.js (or downgrading) will not change the executable. End users do not need to do anything special to install prerequisites. They just download and run the application.

Challenges

The ability to generate an executable from JavaScript helps the language work in even more scenarios than it has before. After all, executables are a fundamental concept, one of the oldest in computing. Just because JavaScript can now be easily used as a source of “programs-without-runtimes” doesn’t alleviate the natural challenges which impact all executables.

First, users do not always update their executables as frequently as developers would like. There are ways to administer automatic updates, but it is the responsibility of developers to create such a mechanism. Generating an executable is not a substitute for security. Do not make the mistake of thinking code which is compiled is impervious to malicious use. Installers can be hard to create. In a world where npm install has felt normal, developers will need a different way to distribute executables. Tools like homebrew and choco help, but distribution of commercial applications still have the same installation challenges. Runtimes like Node.js and Deno bridge many cross-platform gaps, but not all of them. Generating an executable does not alleviate these problems.

Summary