DEV Community

Cover image for The final step: How to package a Node.JS application as an exe
Nhlanhla Lucky Nkosi
Nhlanhla Lucky Nkosi

Posted on • Updated on

The final step: How to package a Node.JS application as an exe

“To a man with a hammer, everything looks like a nail.” — Twain/Maslow/Kaplan/Baruch/Buddha/Unknown.

We all have our go-to tools; that language, framework, and/or IDE that we swear we can do anything with. Personally, I enjoy pushing the limits of whatever tool or programming language I use at the time. Currently, JavaScript is my hammer, and I hit everything with it.

I was recently asked to build a "simple app" that did some administrative tasks. As with most things lately, I decided to use JavaScript to build it and only found out at the end of my development that I was expected to deliver this app as a .exe file to run on windows. Now that I had written all the wonderful Node.JS code, I had to answer the question: how do we package our application share it as an executable.

There are numerous online resources aimed at teaching you how to build a Node.JS application. This is great since node, especially when reinforced with the myriad of open-source packages you can add with npm and yarn, is a great way of building applications of varying sizes and complexities.

JavaScript is most commonly used for web development. Since sharing our creation on the web is such a common part of the web development ecosystem, we have a lot of hosting services that package and run our Node.JS code, leaving us only with the responsibility of giving them our code.

What happens when we need to build a simple application that runs on a custom server somewhere? Most developers that use languages like Java and the c-family languages will simply go for building an executable programme from their code so that the application is self-contained and they don't need to share their actual code. JavaScript developers, how do we go about doing this; how do we build an executable from our Node.JS code without containerization?


The first option is to use pkg. It is a command-line interface that enables the developer to create executables from Node.JS projects; allowing you to run the app even on environments that do not have Node.JS installed on them. Use cases include being able to share your app without sharing your source code thereby equipping you to create cross-platform commercial and demo copies of your application without needing to re-code the entire application or install dependencies on the machine that runs the application.

Getting started

To install pkg
npm install -g pkg

To check if the pkg is correctly installed, you can run the following command: pkg.

Most people have the entry point of their Node.JS application as an index.js file. If you build a package with no configuration, it will name your executable index.exe which is not a very meaningful name. I would, therefore, advise that you give this file a more meaningful name, like 'lucky-example-node-executable.js' but since I'm lazy to retype this name in the rest of the article, I'll call my example file 'lene.js'. With lene.js as the entry point to my Node app, I can package my app by running the following command:
pkg lene.js

Running the above command will generate three programmes; namely an executable for Windows, macOS, and Linux as shown in the image below:
pkg output
As shown in the above image, the command generates files that are aptly-named in accordance with the target platform of each programme.

Suppose you only need to run your programme on one platform, say a windows server. Then packaging your app for all three targets would not necessarily make sense or be a good thing to do. In this instance, you can specify your target platform using the following command:
pkg -t <targets> <programme-entry>.js
where <programme-entry>.js is the file name of the entry point into your Node project. In our example here, the file name is lene.js.

<targets> is a comma-separated list of target platforms that follow a specific 3-part format. Each part specifies different platform attributes that help tell pkg how exactly to package our app. These attributes are nodeRange-platform-architecture. The first specifies the version of Node to be used by your application and specified as node${n} or node latest to use the latest available LTS version of Node. The second is the platform, specified as one of the following supported strings:

  • freebsd,
  • linux,
  • alpine,
  • macos,
  • win.

and the last part is the target architecture namely x64, x86, armv6 or armv7.

So pkg -t node12-linux,node10-win-x86 lene.js will fetch the necessary dependencies required to package the application and use node version 12 to build a Linux executable and then Node version 10 to build a Windows x86 executable.

This is a quick start guide to using pkg. This was the most beginner-friendly solution I could find. For a simple application, you need almost no further configuration. The only extra work you might need is if you import dependencies based on variables. In this scenario, you would have to specify the files - scripts and assets - manually in pkg property of your package.json file in order for them to get packaged with your application code.

Pkg is only one of a number of ways to do this. I also found Nexe which is also a command-line utility that compiles your Node.js application into a single executable file.

Let me know what you think of pkg and if you'd like to make a comparison of pkg and nexe. Do you have any other similar tools that I can look at? Please let me know in the comments section.

I hope you found this article useful.

Top comments (3)

filipparyz profile image
Filip Paryż

I've used PKG to package my app, but what should I do if I'm using a folder with files that are added and removed by the user? If I package them, the node.js can only read those files, not save to them.
If I don't package them, should I write another app that is an installer which creates the folder structure and copies the files to specific folders on user PC?

ssianik profile image
Syed Sirajul Islam Anik

Just in case someone wants to use in gh workflows.

robb-keayes profile image
Robb Keayes

2024, punycode has been deprecated :(