1{ 2 "type": "module", 3 "source": "doc/api/single-executable-applications.md", 4 "modules": [ 5 { 6 "textRaw": "Single executable applications", 7 "name": "single_executable_applications", 8 "introduced_in": "v18.16.0", 9 "meta": { 10 "added": [ 11 "v19.7.0", 12 "v18.16.0" 13 ], 14 "changes": [] 15 }, 16 "stability": 1, 17 "stabilityText": "Experimental: This feature is being designed and will change.", 18 "desc": "<p><strong>Source Code:</strong> <a href=\"https://github.com/nodejs/node/blob/v18.18.2/src/node_sea.cc\">src/node_sea.cc</a></p>\n<p>This feature allows the distribution of a Node.js application conveniently to a\nsystem that does not have Node.js installed.</p>\n<p>Node.js supports the creation of <a href=\"https://github.com/nodejs/single-executable\">single executable applications</a> by allowing\nthe injection of a JavaScript file into the <code>node</code> 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.</p>\n<p>The single executable application feature only supports running a single\nembedded <a href=\"modules.html#modules-commonjs-modules\">CommonJS</a> file.</p>\n<p>A bundled JavaScript file can be turned into a single executable application\nwith any tool which can inject resources into the <code>node</code> binary.</p>\n<p>Here are the steps for creating a single executable application using one such\ntool, <a href=\"https://github.com/nodejs/postject\">postject</a>:</p>\n<ol>\n<li>\n<p>Create a JavaScript file:</p>\n<pre><code class=\"language-console\">$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js\n</code></pre>\n</li>\n<li>\n<p>Create a copy of the <code>node</code> executable and name it according to your needs:</p>\n<pre><code class=\"language-console\">$ cp $(command -v node) hello\n</code></pre>\n</li>\n<li>\n<p>Inject the JavaScript file into the copied binary by running <code>postject</code> with\nthe following options:</p>\n<ul>\n<li><code>hello</code> - The name of the copy of the <code>node</code> executable created in step 2.</li>\n<li><code>NODE_JS_CODE</code> - The name of the resource / note / section in the binary\nwhere the contents of the JavaScript file will be stored.</li>\n<li><code>hello.js</code> - The name of the JavaScript file created in step 1.</li>\n<li><code>--sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2</code> - The\n<a href=\"https://www.electronjs.org/docs/latest/tutorial/fuses\">fuse</a> used by the Node.js project to detect if a file has been injected.</li>\n<li><code>--macho-segment-name NODE_JS</code> (only needed on macOS) - The name of the\nsegment in the binary where the contents of the JavaScript file will be\nstored.</li>\n</ul>\n<p>To summarize, here is the required command for each platform:</p>\n<ul>\n<li>\n<p>On systems other than macOS:</p>\n<pre><code class=\"language-console\">$ npx postject hello NODE_JS_CODE hello.js \\\n --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2\n</code></pre>\n</li>\n<li>\n<p>On macOS:</p>\n<pre><code class=\"language-console\">$ npx postject hello NODE_JS_CODE hello.js \\\n --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \\\n --macho-segment-name NODE_JS\n</code></pre>\n</li>\n</ul>\n</li>\n<li>\n<p>Run the binary:</p>\n<pre><code class=\"language-console\">$ ./hello world\nHello, world!\n</code></pre>\n</li>\n</ol>", 19 "modules": [ 20 { 21 "textRaw": "Notes", 22 "name": "notes", 23 "modules": [ 24 { 25 "textRaw": "`require(id)` in the injected module is not file based", 26 "name": "`require(id)`_in_the_injected_module_is_not_file_based", 27 "desc": "<p><code>require()</code> in the injected module is not the same as the <a href=\"modules.html#requireid\"><code>require()</code></a>\navailable to modules that are not injected. It also does not have any of the\nproperties that non-injected <a href=\"modules.html#requireid\"><code>require()</code></a> has except <a href=\"modules.html#accessing-the-main-module\"><code>require.main</code></a>. 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.</p>\n<p>Instead of relying on a file based <code>require()</code>, users can bundle their\napplication into a standalone JavaScript file to inject into the executable.\nThis also ensures a more deterministic dependency graph.</p>\n<p>However, if a file based <code>require()</code> is still needed, that can also be achieved:</p>\n<pre><code class=\"language-js\">const { createRequire } = require('node:module');\nrequire = createRequire(__filename);\n</code></pre>", 28 "type": "module", 29 "displayName": "`require(id)` in the injected module is not file based" 30 }, 31 { 32 "textRaw": "`__filename` and `module.filename` in the injected module", 33 "name": "`__filename`_and_`module.filename`_in_the_injected_module", 34 "desc": "<p>The values of <code>__filename</code> and <code>module.filename</code> in the injected module are\nequal to <a href=\"process.html#processexecpath\"><code>process.execPath</code></a>.</p>", 35 "type": "module", 36 "displayName": "`__filename` and `module.filename` in the injected module" 37 }, 38 { 39 "textRaw": "`__dirname` in the injected module", 40 "name": "`__dirname`_in_the_injected_module", 41 "desc": "<p>The value of <code>__dirname</code> in the injected module is equal to the directory name\nof <a href=\"process.html#processexecpath\"><code>process.execPath</code></a>.</p>", 42 "type": "module", 43 "displayName": "`__dirname` in the injected module" 44 }, 45 { 46 "textRaw": "Single executable application creation process", 47 "name": "single_executable_application_creation_process", 48 "desc": "<p>A tool aiming to create a single executable Node.js application must\ninject the contents of a JavaScript file into:</p>\n<ul>\n<li>a resource named <code>NODE_JS_CODE</code> if the <code>node</code> binary is a <a href=\"https://en.wikipedia.org/wiki/Portable_Executable\">PE</a> file</li>\n<li>a section named <code>NODE_JS_CODE</code> in the <code>NODE_JS</code> segment if the <code>node</code> binary\nis a <a href=\"https://en.wikipedia.org/wiki/Mach-O\">Mach-O</a> file</li>\n<li>a note named <code>NODE_JS_CODE</code> if the <code>node</code> binary is an <a href=\"https://en.wikipedia.org/wiki/Executable_and_Linkable_Format\">ELF</a> file</li>\n</ul>\n<p>Search the binary for the\n<code>NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2:0</code> <a href=\"https://www.electronjs.org/docs/latest/tutorial/fuses\">fuse</a> string and flip the\nlast character to <code>1</code> to indicate that a resource has been injected.</p>", 49 "type": "module", 50 "displayName": "Single executable application creation process" 51 }, 52 { 53 "textRaw": "Platform support", 54 "name": "platform_support", 55 "desc": "<p>Single-executable support is tested regularly on CI only on the following\nplatforms:</p>\n<ul>\n<li>Windows</li>\n<li>macOS</li>\n<li>Linux (AMD64 only)</li>\n</ul>\n<p>This is due to a lack of better tools to generate single-executables that can be\nused to test this feature on other platforms.</p>\n<p>Suggestions for other resource injection tools/workflows are welcomed. Please\nstart a discussion at <a href=\"https://github.com/nodejs/single-executable/discussions\">https://github.com/nodejs/single-executable/discussions</a>\nto help us document them.</p>", 56 "type": "module", 57 "displayName": "Platform support" 58 } 59 ], 60 "type": "module", 61 "displayName": "Notes" 62 } 63 ], 64 "type": "module", 65 "displayName": "Single executable applications" 66 } 67 ] 68}