Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/mongodb-js/boxednode

📦 boxednode – Ship a JS file with Node.js in a box
https://github.com/mongodb-js/boxednode

Last synced: about 2 months ago
JSON representation

📦 boxednode – Ship a JS file with Node.js in a box

Lists

README

        

# 📦 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:

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

## CLI usage

```sh
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

```js
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;

// 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](https://github.com/nodejs/node/blob/master/BUILDING.md) for
a complete list of tools that may be necessary.

## Releasing

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

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

## Not supported

- Multiple JS files

## Similar projects

- [pkg](https://www.npmjs.com/package/pkg)
- [nexe](https://www.npmjs.com/package/nexe)

## License

[Apache-2.0](./LICENSE)