@@ -10,15 +10,17 @@ This feature allows the distribution of a Node.js application conveniently to a
1010system that does not have Node.js installed.
1111
1212Node.js supports the creation of [ single executable applications] [ ] by allowing
13- the injection of a JavaScript file into the ` node ` binary. During start up, the
14- program checks if anything has been injected. If the script is found, it
15- executes its contents. Otherwise Node.js operates as it normally does.
13+ the injection of a blob prepared by Node.js, which can contain a bundled script,
14+ into the ` node ` binary. During start up, the program checks if anything has been
15+ injected. If the blob is found, it executes the script in the blob. Otherwise
16+ Node.js operates as it normally does.
1617
17- The single executable application feature only supports running a single
18- embedded [ CommonJS] [ ] file .
18+ The single executable application feature currently only supports running a
19+ single embedded script using the [ CommonJS] [ ] module system .
1920
20- A bundled JavaScript file can be turned into a single executable application
21- with any tool which can inject resources into the ` node ` binary.
21+ Users can create a single executable application from their bundled script
22+ with the ` node ` binary itself and any tool which can inject resources into the
23+ binary.
2224
2325Here are the steps for creating a single executable application using one such
2426tool, [ postject] [ ] :
@@ -28,12 +30,24 @@ tool, [postject][]:
2830 $ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
2931 ```
3032
31- 2 . Create a copy of the ` node ` executable and name it according to your needs:
33+ 2 . Create a configuration file building a blob that can be injected into the
34+ single executable application (see
35+ [ Generating single executable preparation blobs] [ ] for details):
36+ ``` console
37+ $ echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
38+ ```
39+
40+ 3 . Generate the blob to be injected:
41+ ``` console
42+ $ node --experimental-sea-config sea-config.json
43+ ```
44+
45+ 4 . Create a copy of the ` node ` executable and name it according to your needs:
3246 ``` console
3347 $ cp $(command -v node) hello
3448 ```
3549
36- 3 . Remove the signature of the binary:
50+ 5 . Remove the signature of the binary:
3751
3852 * On macOS:
3953
@@ -50,35 +64,35 @@ tool, [postject][]:
5064 $ signtool remove /s hello
5165 ```
5266
53- 4 . Inject the JavaScript file into the copied binary by running ` postject ` with
67+ 6 . Inject the blob into the copied binary by running ` postject ` with
5468 the following options:
5569
5670 * ` hello ` - The name of the copy of the ` node ` executable created in step 2.
57- * ` NODE_JS_CODE ` - The name of the resource / note / section in the binary
58- where the contents of the JavaScript file will be stored.
59- * ` hello.js ` - The name of the JavaScript file created in step 1.
60- * ` --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 ` - The
71+ * ` NODE_SEA_BLOB ` - The name of the resource / note / section in the binary
72+ where the contents of the blob will be stored.
73+ * ` sea-prep.blob ` - The name of the blob created in step 1.
74+ * ` --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 ` - The
6175 [ fuse] [ ] used by the Node.js project to detect if a file has been injected.
62- * ` --macho-segment-name NODE_JS ` (only needed on macOS) - The name of the
63- segment in the binary where the contents of the JavaScript file will be
76+ * ` --macho-segment-name NODE_SEA ` (only needed on macOS) - The name of the
77+ segment in the binary where the contents of the blob will be
6478 stored.
6579
6680 To summarize, here is the required command for each platform:
6781
6882 * On systems other than macOS:
6983 ``` console
70- $ npx postject hello NODE_JS_CODE hello.js \
71- --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2
84+ $ npx postject hello NODE_SEA_BLOB sea-prep.blob \
85+ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
7286 ```
7387
7488 * On macOS:
7589 ```console
76- $ npx postject hello NODE_JS_CODE hello.js \
77- --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
78- --macho-segment-name NODE_JS
90+ $ npx postject hello NODE_SEA_BLOB sea-prep.blob \
91+ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
92+ --macho-segment-name NODE_SEA
7993 ```
8094
81- 5 . Sign the binary:
95+ 7 . Sign the binary:
8296
8397 * On macOS:
8498
@@ -95,12 +109,33 @@ tool, [postject][]:
95109 $ signtool sign /fd SHA256 hello
96110 ```
97111
98- 6 . Run the binary:
112+ 8 . Run the binary:
99113 ``` console
100114 $ ./hello world
101115 Hello, world!
102116 ```
103117
118+ ## Generating single executable preparation blobs
119+
120+ Single executable preparation blobs that are injected into the application can
121+ be generated using the ` --experimental-sea-config ` flag of the Node.js binary
122+ that will be used to build the single executable. It takes a path to a
123+ configuration file in JSON format. If the path passed to it isn't absolute,
124+ Node.js will use the path relative to the current working directory.
125+
126+ The configuration currently reads the following top-level fields:
127+
128+ ``` json
129+ {
130+ "main" : " /path/to/bundled/script.js" ,
131+ "output" : " /path/to/write/the/generated/blob.blob"
132+ }
133+ ```
134+
135+ If the paths are not absolute, Node.js will use the path relative to the
136+ current working directory. The version of the Node.js binary used to produce
137+ the blob must be the same as the one to which the blob will be injected.
138+
104139## Notes
105140
106141### ` require(id) ` in the injected module is not file based
@@ -135,15 +170,16 @@ of [`process.execPath`][].
135170### Single executable application creation process
136171
137172A tool aiming to create a single executable Node.js application must
138- inject the contents of a JavaScript file into:
173+ inject the contents of the blob prepared with ` --experimental-sea-config" `
174+ into:
139175
140- * a resource named ` NODE_JS_CODE ` if the ` node ` binary is a [ PE] [ ] file
141- * a section named ` NODE_JS_CODE ` in the ` NODE_JS ` segment if the ` node ` binary
176+ * a resource named ` NODE_SEA_BLOB ` if the ` node ` binary is a [ PE] [ ] file
177+ * a section named ` NODE_SEA_BLOB ` in the ` NODE_SEA ` segment if the ` node ` binary
142178 is a [ Mach-O] [ ] file
143- * a note named ` NODE_JS_CODE ` if the ` node ` binary is an [ ELF] [ ] file
179+ * a note named ` NODE_SEA_BLOB ` if the ` node ` binary is an [ ELF] [ ] file
144180
145181Search the binary for the
146- ` NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 :0` [ fuse] [ ] string and flip the
182+ ` NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 :0` [ fuse] [ ] string and flip the
147183last character to ` 1 ` to indicate that a resource has been injected.
148184
149185### Platform support
@@ -165,6 +201,7 @@ to help us document them.
165201
166202[ CommonJS ] : modules.md#modules-commonjs-modules
167203[ ELF ] : https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
204+ [ Generating single executable preparation blobs ] : #generating-single-executable-preparation-blobs
168205[ Mach-O ] : https://en.wikipedia.org/wiki/Mach-O
169206[ PE ] : https://en.wikipedia.org/wiki/Portable_Executable
170207[ Windows SDK ] : https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
0 commit comments