{ "type": "module", "source": "doc/api/single-executable-applications.md", "modules": [ { "textRaw": "Single executable applications", "name": "single_executable_applications", "introduced_in": "v18.16.0", "meta": { "added": [ "v19.7.0", "v18.16.0" ], "changes": [] }, "stability": 1, "stabilityText": "Experimental: This feature is being designed and will change.", "desc": "
Source Code: src/node_sea.cc
\nThis feature allows the distribution of a Node.js application conveniently to a\nsystem that does not have Node.js installed.
\nNode.js supports the creation of single executable applications by allowing\nthe injection of a JavaScript file into the node
binary. During start up, the\nprogram checks if anything has been injected. If the script is found, it\nexecutes its contents. Otherwise Node.js operates as it normally does.
The single executable application feature only supports running a single\nembedded CommonJS file.
\nA bundled JavaScript file can be turned into a single executable application\nwith any tool which can inject resources into the node
binary.
Here are the steps for creating a single executable application using one such\ntool, postject:
\nCreate a JavaScript file:
\n$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js\n
\nCreate a copy of the node
executable and name it according to your needs:
$ cp $(command -v node) hello\n
\nInject the JavaScript file into the copied binary by running postject
with\nthe following options:
hello
- The name of the copy of the node
executable created in step 2.NODE_JS_CODE
- The name of the resource / note / section in the binary\nwhere the contents of the JavaScript file will be stored.hello.js
- The name of the JavaScript file created in step 1.--sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2
- The\nfuse used by the Node.js project to detect if a file has been injected.--macho-segment-name NODE_JS
(only needed on macOS) - The name of the\nsegment in the binary where the contents of the JavaScript file will be\nstored.To summarize, here is the required command for each platform:
\nOn systems other than macOS:
\n$ npx postject hello NODE_JS_CODE hello.js \\\n --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2\n
\nOn macOS:
\n$ npx postject hello NODE_JS_CODE hello.js \\\n --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \\\n --macho-segment-name NODE_JS\n
\nRun the binary:
\n$ ./hello world\nHello, world!\n
\nrequire()
in the injected module is not the same as the require()
\navailable to modules that are not injected. It also does not have any of the\nproperties that non-injected require()
has except require.main
. It\ncan only be used to load built-in modules. Attempting to load a module that can\nonly be found in the file system will throw an error.
Instead of relying on a file based require()
, users can bundle their\napplication into a standalone JavaScript file to inject into the executable.\nThis also ensures a more deterministic dependency graph.
However, if a file based require()
is still needed, that can also be achieved:
const { createRequire } = require('node:module');\nrequire = createRequire(__filename);\n
",
"type": "module",
"displayName": "`require(id)` in the injected module is not file based"
},
{
"textRaw": "`__filename` and `module.filename` in the injected module",
"name": "`__filename`_and_`module.filename`_in_the_injected_module",
"desc": "The values of __filename
and module.filename
in the injected module are\nequal to process.execPath
.
The value of __dirname
in the injected module is equal to the directory name\nof process.execPath
.
A tool aiming to create a single executable Node.js application must\ninject the contents of a JavaScript file into:
\nNODE_JS_CODE
if the node
binary is a PE fileNODE_JS_CODE
in the NODE_JS
segment if the node
binary\nis a Mach-O fileNODE_JS_CODE
if the node
binary is an ELF fileSearch the binary for the\nNODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2:0
fuse string and flip the\nlast character to 1
to indicate that a resource has been injected.
Single-executable support is tested regularly on CI only on the following\nplatforms:
\nThis is due to a lack of better tools to generate single-executables that can be\nused to test this feature on other platforms.
\nSuggestions for other resource injection tools/workflows are welcomed. Please\nstart a discussion at https://github.com/nodejs/single-executable/discussions\nto help us document them.
", "type": "module", "displayName": "Platform support" } ], "type": "module", "displayName": "Notes" } ], "type": "module", "displayName": "Single executable applications" } ] }