📦 Bundle Node.js into single executable binary

August 20, 2022

Node.js 🐢, the asynchronous event-driven JavaScript runtime, has unparalleled support for file-system access, among other things – opening up the door to endless possiblities! However, Node.js often loses out to other runtimes/languages in cases where being able to package a single, executable application simplifies distribution and management of what needs to be delivered.

While there are components/approaches for doing this, they need to be better documented and evangelized so that this is not seen as a barrier for using Node.js in these situations. This is important to support the expansion of where/when Node.js is used in building solutions.

This article addresses 2 major concerns in the Node.js ecosystem: bundling and packaging. Let’s talk about them briefly.

Bundling is the concept of merging the code, and all its dependencies into a single file. This is commonly seen for frontend development.

However, using the ESM packaging format has one advantage than CJS: tree-shaking. Tree-shaking is the concept of removing unused code from a dependency. Tools: esbuild, parcel, webpack, rollup, terser.

Packaging in Node.js is concept of creating a single executable binary, which includes the source code and the Node.js runtime. This way, Node.js will not be needed to be installed on end-user’s machine.

During the process, the tool parses the source code, detects calls to require(), traverses the dependencies, and includes them into executable. Usually the source code is compiled into bytecode using the V8 engine. Tools: pkg, ncc, nexe.

esbuild to bundle

  • An extremely fast JavaScript and CSS bundler and minifier
  • Most convenient
  • Fastest in comparison
  • Support for TypeScript syntax, ESM, and CJS
  • Supports tree-shaking for ESM
  • Supports minification and source maps
# Output CommonJS bundle
$ npx esbuild index.js  --bundle --outfile=build.cjs \
--format=cjs --platform=node
Enter fullscreen modeExit fullscreen mode
# Output ESM bundle
# Note that, you may not need the --banner flag.
# But, in some cases, require() and __dirname are needed.
$ npx esbuild index.js  --bundle --outfile=build.mjs \
--format=esm --platform=node --banner:js="
import {createRequire} from 'module';
const require = createRequire(import.meta.url);
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));"
Enter fullscreen modeExit fullscreen mode

pkg to package

  • Package your Node.js project into an executable
  • Instantly make executables for Windows, Mac, Linux, etc
  • No need to install Node.js, or hundreds of dependencies
$ npx pkg index.js
Enter fullscreen modeExit fullscreen mode

Source link

Comments 0

Leave a Reply

Your email address will not be published. Required fields are marked *