@@ -10,15 +10,17 @@ This feature allows the distribution of a Node.js application conveniently to a
10
10
system that does not have Node.js installed.
11
11
12
12
Node.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.
16
17
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 .
19
20
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.
22
24
23
25
Here are the steps for creating a single executable application using one such
24
26
tool, [ postject] [ ] :
@@ -28,12 +30,24 @@ tool, [postject][]:
28
30
$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
29
31
```
30
32
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:
32
46
``` console
33
47
$ cp $(command -v node) hello
34
48
```
35
49
36
- 3 . Remove the signature of the binary:
50
+ 5 . Remove the signature of the binary:
37
51
38
52
* On macOS:
39
53
@@ -50,35 +64,35 @@ tool, [postject][]:
50
64
$ signtool remove /s hello
51
65
```
52
66
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
54
68
the following options:
55
69
56
70
* ` 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
61
75
[ 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
64
78
stored.
65
79
66
80
To summarize, here is the required command for each platform:
67
81
68
82
* On systems other than macOS:
69
83
``` 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
72
86
```
73
87
74
88
* On macOS:
75
89
```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
79
93
```
80
94
81
- 5 . Sign the binary:
95
+ 7 . Sign the binary:
82
96
83
97
* On macOS:
84
98
@@ -95,12 +109,33 @@ tool, [postject][]:
95
109
$ signtool sign /fd SHA256 hello
96
110
```
97
111
98
- 6 . Run the binary:
112
+ 8 . Run the binary:
99
113
``` console
100
114
$ ./hello world
101
115
Hello, world!
102
116
```
103
117
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
+
104
139
## Notes
105
140
106
141
### ` require(id) ` in the injected module is not file based
@@ -135,15 +170,16 @@ of [`process.execPath`][].
135
170
### Single executable application creation process
136
171
137
172
A 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:
139
175
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
142
178
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
144
180
145
181
Search 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
147
183
last character to ` 1 ` to indicate that a resource has been injected.
148
184
149
185
### Platform support
@@ -165,6 +201,7 @@ to help us document them.
165
201
166
202
[ CommonJS ] : modules.md#modules-commonjs-modules
167
203
[ ELF ] : https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
204
+ [ Generating single executable preparation blobs ] : #generating-single-executable-preparation-blobs
168
205
[ Mach-O ] : https://en.wikipedia.org/wiki/Mach-O
169
206
[ PE ] : https://en.wikipedia.org/wiki/Portable_Executable
170
207
[ Windows SDK ] : https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
0 commit comments