Skip to content

πŸ“¦ boxednode – Ship a JS file with Node.js in a box

License

Notifications You must be signed in to change notification settings

mongodb-js/boxednode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“¦ boxednode – Ship a JS file with Node.js in a box

Take

  1. A JavaScript file
  2. Node.js

and pack them up as a single binary.

For example:

$ cat example.js
console.log('Hello, world!');
$ boxednode -s example.js -t example
$ ./example
Hello, world!

CLI usage

Options:
      --version         Show version number                            [boolean]
  -c, --clean           Clean up temporary directory after success     [boolean]
  -s, --source          Source .js file                      [string] [required]
  -t, --target          Target executable file               [string] [required]
  -n, --node-version    Node.js version or semver version range
                                                         [string] [default: "*"]
  -C, --configure-args  Extra ./configure or vcbuild arguments, comma-separated
                                                                        [string]
  -M, --make-args       Extra make or vcbuild arguments, comma-separated[string]
      --tmpdir          Temporary directory for compiling Node.js source[string]
      --help            Show help                                      [boolean]

Node.js versions may be specific versions, semver ranges, or any of the aliases supported by https://github.com/pkgjs/nv/.

Programmatic API

type CompilationOptions = {
  // Single Node.js version, semver range or shorthand alias to pick from
  nodeVersionRange: string;

  // Optional temporary directory for storing and compiling Node.js source
  tmpdir?: string;

  // A single .js file that serves as the entry point for the generated binary
  sourceFile: string;

  // The file path to the target binary
  targetFile: string;

  // Optional list of extra arguments to be passed to `./configure` or `vcbuild`
  configureArgs?: string[];

    // Optional list of extra arguments to be passed to `make` or `vcbuild`
  makeArgs?: string[];

  // If true, remove the temporary directory created earlier when done
  clean?: boolean;

  // Environment variables for build processes. Defaults to inheriting
  // environment variables.
  env?: { [name: string]: string | undefined };

  // Specify the entrypoint target name. If this is 'foo', then the resulting
  // binary will be able to load the source file as 'require("foo/foo")'.
  // This defaults to the basename of sourceFile, e.g. 'bar' for '/path/bar.js'.
  namespace?: string;

  // A list of native addons to link in.
  addons?: AddonConfig[];

  // Make sure the binary works for addons that use the `bindings` npm package,
  // which would otherwise not be compatible with a single-binary model.
  // By default, this is enabled if any addons are specified and
  // disabled otherwise.
  // (This will make `fs.accessSync('/node_modules')` not throw an exception.)
  enableBindingsPatch?: boolean;

  // A custom hook that is run just before starting the compile step.
  preCompileHook?: (nodeSourceTree: string, options: CompilationOptions) => void | Promise<void>;

  // A list of attributes to set on the generated executable. This is currently
  // only being used on Windows.
  executableMetadata?: ExecutableMetadata;
};

type AddonConfig = {
  // Path to the root directory of the target addon, i.e. the one containing
  // a binding.gyp file.
  path: string;

  // A regular expression to match for `require()` calls from the main file.
  // `require(str)` will return the linked binding if `str` matches.
  // This will *not* be the same as `require(path)`, which usually is a JS
  // wrapper around this.
  requireRegexp: RegExp;
};

type ExecutableMetadata = {
  // Sets Windows .exe InternalName and ProductName
  name?: string;

  // Sets Windows .exe FileDescription
  description?: string;

  // Sets Windows .exe FileVersion and ProductVersion
  version?: string;

  // Sets Windows .exe CompanyName
  manufacturer?: string;

  // Sets Windows .exe LegalCopyright
  copyright?: string;

  // Provides the path to a .ico file to use for the
  // Windows .exe file.
  icon?: string;
};

export function compileJSFileAsBinary(options: CompilationOptions);

The BOXEDNODE_CONFIGURE_ARGS environment variable will be read as a comma-separated list of strings and added to configureArgs, and likewise BOXEDNODE_MAKE_ARGS to makeArgs.

Why this solution

We needed a simple and reliable way to create shippable binaries from a source file.

Unlike others, this solution:

  • Works for Node.js v12.x and above, without being tied to specific versions
  • Uses only officially supported, stable Node.js APIs
  • Creates binaries that are not bloated with extra features
  • Creates binaries that can be signed and notarized on macOS
  • Supports linking native addons into the binary

Prerequisites

This package compiles Node.js from source. See the Node.js BUILDING.md file for a complete list of tools that may be necessary.

Releasing

To release a new version, run the following command in main:

npm version [patch|minor|major] && npm it & npm publish && git push origin main --tags

Not supported

  • Multiple JS files

Similar projects

License

Apache-2.0