DEV Community

Cover image for Vercel's pkg - Package your Node.js app into a single executable
Sivamuthu Kumar
Sivamuthu Kumar

Posted on • Originally published at blog.sivamuthukumar.com

Vercel's pkg - Package your Node.js app into a single executable

Hello all, In this short post, we will take a look at Vercel's pkg - how we can package the Node.js app into a single executable.

When we are developing a Node.js application, it totally makes sense to install dev tools, dependencies to build and run an application. In the end, the user is interested in running the app and not the code and libraries the developer integrates. In the Node.js world, it's getting tougher that - when we release the packages, the sources are also released along with the 100s of dependency code as node_modules. It brings the necessity of the package mechanism to build and distribute the node library as a single executable - with the runtime or as a single file to run on already installed nodejs runtime.

Build the Node.js app into a single file - ncc

GitHub logo vercel / ncc

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.

ncc - Simple CLI for compiling a Node.js module into a single file, together with all its dependencies, gcc-style.

Install the ncc using the below command.

npm i -g @vercel/ncc
Enter fullscreen mode Exit fullscreen mode

Build the project using this simple command. It will output the Node.js compact build of app.js into dist/app.js

ncc build app.js -o dist
Enter fullscreen mode Exit fullscreen mode

Package the Node.js app into a single executable - pkg

GitHub logo vercel / pkg

Package your Node.js project into an executable

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.

Install the pkg using the below command

npm install -g pkg
Enter fullscreen mode Exit fullscreen mode

Run the pkg build targeting multiple platforms. It will create the executable in the dist directory

pkg -t node12-linux,node14-linux,node14-win index.js
Enter fullscreen mode Exit fullscreen mode

Targets

pkg can generate executables for several target machines at a time. You can specify a comma-separated list of targets via --targets option. A canonical target consists of 3 elements, separated by dashes, for example node12-macos-x64 or node14-linux-arm64:

  • nodeRange (node8), node10, node12, node14, node16 or latest
  • platform alpine, linux, linuxstatic, win, macos, (freebsd)
  • arch x64, arm64, (armv6, armv7)

Demo

Check out this repo

Run locally and verify whether it's logging the telemetry in the console.

➜ vercel-pkg-demo git:(main) npm i
➜ vercel-pkg-demo git:(main) node index.js
IoT Device Initialized
Telemetry: {"temperature":"56.12","humidity":"52.11"}
Telemetry: {"temperature":"68.30","humidity":"51.90"}
Telemetry: {"temperature":"53.78","humidity":"53.72"}
Enter fullscreen mode Exit fullscreen mode

Run npm run build to build the package into executable.

"scripts": {
    "build": "npx pkg -t linux,macos,win . --out-path dist"
 },
Enter fullscreen mode Exit fullscreen mode

The build steps are added in GitHub Actions and you can see the executable files are added as artifacts after build.

image.png

Let's download the executable and run and see whether we are seeing the same output.

./hvac-demo-device-macos
➜  dist git:(main)  ./hvac-demo-device-macos
IoT Device Initialized
Telemetry: {"temperature":"70.59","humidity":"46.23"}
Telemetry: {"temperature":"69.76","humidity":"49.93"}
Telemetry: {"temperature":"62.15","humidity":"58.93"}
Enter fullscreen mode Exit fullscreen mode

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)
  • No need to install Node.js and npm to run the packaged application
  • Put your assets inside the executable to make it even more portable

Conclusion

I've found vercel's pkg very useful in order to achieve a similar target and package a whole application into standalone executables for multiplatform. It's nice to have a single file that can be started right away without any external dependency. And also, it prevents from having to distribute the full sources. You can extend it for including assets and other requirements.

I'm Siva - working as Sr. Software Architect at Computer Enterprises Inc from Orlando. I'm an AWS Community builder, Auth0 Ambassador and I am going to write a lot about Cloud, Containers, IoT, and Devops. If you are interested in any of that, make sure to follow me if you haven’t already. Please follow me @ksivamuthu Twitter or check out my blogs at blog.sivamuthukumar.com

Top comments (3)

Collapse
 
bashirirshad profile image
Bashir Irshad

I packaged my node.js app with pkg. my app consists static folder which contains images. but with the packaged app, I can not access my images. with out packaging the images are accessible.

it gives me this message:
GET localhost/owners/1634464527932imag... 404 (Not Found)

Collapse
 
ksivamuthu profile image
Sivamuthu Kumar

You need to configure the "assets" in pkg configuration for static assets.

 "assets": [ "assets/**/*", "images/**/*" ]
Enter fullscreen mode Exit fullscreen mode

Check this configuration here. github.com/vercel/pkg#config

Collapse
 
pedrodlafaria profile image
Pedro Faria

What does pkg actually do to create the executable? Does it include the whole runtime environment of Node.js, or does it somehow compile Javascript to machine code? Thanks!