@@ -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,23 @@ 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:
35
+ ``` console
36
+ $ echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
37
+ ```
38
+
39
+ 3 . Generate the blob to be injected:
40
+ ``` console
41
+ $ node --experimental-sea-config sea-config.json
42
+ ```
43
+
44
+ 4 . Create a copy of the ` node ` executable and name it according to your needs:
32
45
``` console
33
46
$ cp $(command -v node) hello
34
47
```
35
48
36
- 3 . Remove the signature of the binary:
49
+ 5 . Remove the signature of the binary:
37
50
38
51
* On macOS:
39
52
@@ -50,35 +63,35 @@ tool, [postject][]:
50
63
$ signtool remove /s hello
51
64
```
52
65
53
- 4 . Inject the JavaScript file into the copied binary by running ` postject ` with
66
+ 6 . Inject the blob into the copied binary by running ` postject ` with
54
67
the following options:
55
68
56
69
* ` 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
70
+ * ` NODE_SEA_BLOB ` - The name of the resource / note / section in the binary
71
+ where the contents of the blob will be stored.
72
+ * ` hello.js ` - The name of the blob created in step 1.
73
+ * ` --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 ` - The
61
74
[ 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
75
+ * ` --macho-segment-name NODE_SEA ` (only needed on macOS) - The name of the
76
+ segment in the binary where the contents of the blob will be
64
77
stored.
65
78
66
79
To summarize, here is the required command for each platform:
67
80
68
81
* On systems other than macOS:
69
82
``` console
70
- $ npx postject hello NODE_JS_CODE hello.js \
71
- --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2
83
+ $ npx postject hello NODE_SEA_BLOB hello.js \
84
+ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
72
85
```
73
86
74
87
* On macOS:
75
88
```console
76
- $ npx postject hello NODE_JS_CODE hello.js \
77
- --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
78
- --macho-segment-name NODE_JS
89
+ $ npx postject hello NODE_SEA_BLOB hello.js \
90
+ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
91
+ --macho-segment-name NODE_SEA
79
92
```
80
93
81
- 5 . Sign the binary:
94
+ 7 . Sign the binary:
82
95
83
96
* On macOS:
84
97
@@ -95,12 +108,33 @@ tool, [postject][]:
95
108
$ signtool sign /fd SHA256 hello
96
109
```
97
110
98
- 6 . Run the binary:
111
+ 8 . Run the binary:
99
112
``` console
100
113
$ ./hello world
101
114
Hello, world!
102
115
```
103
116
117
+ ## Generating single executable preparation blobs
118
+
119
+ Single executable preparation blobs that are injected into the application can
120
+ be generated using the ` --experimental-sea-config ` flag of the Node.js binary
121
+ that will be used to build the single executable. It takes a path to a
122
+ configuration file in JSON format. If the path passed to it isn't absolute,
123
+ Node.js will use the path relative to the current working directory.
124
+
125
+ The configuration currently reads the following top-level fields:
126
+
127
+ ``` json
128
+ {
129
+ "main" : " /path/to/bundled/script.js" ,
130
+ "output" : " /path/to/write/the/generated/blob.blob"
131
+ }
132
+ ```
133
+
134
+ If the paths are not absolute, Node.js will use the path relative to the
135
+ current working directory. The version of the Node.js binary used to produce
136
+ the blob must be the same as the one to which the blob will be injected.
137
+
104
138
## Notes
105
139
106
140
### ` require(id) ` in the injected module is not file based
@@ -135,15 +169,16 @@ of [`process.execPath`][].
135
169
### Single executable application creation process
136
170
137
171
A tool aiming to create a single executable Node.js application must
138
- inject the contents of a JavaScript file into:
172
+ inject the contents of the blob prepared with ` --experimental-sea-config" `
173
+ into:
139
174
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
175
+ * a resource named ` NODE_SEA_BLOB ` if the ` node ` binary is a [ PE] [ ] file
176
+ * a section named ` NODE_SEA_BLOB ` in the ` NODE_SEA ` segment if the ` node ` binary
142
177
is a [ Mach-O] [ ] file
143
- * a note named ` NODE_JS_CODE ` if the ` node ` binary is an [ ELF] [ ] file
178
+ * a note named ` NODE_SEA_BLOB ` if the ` node ` binary is an [ ELF] [ ] file
144
179
145
180
Search the binary for the
146
- ` NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 :0` [ fuse] [ ] string and flip the
181
+ ` NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 :0` [ fuse] [ ] string and flip the
147
182
last character to ` 1 ` to indicate that a resource has been injected.
148
183
149
184
### Platform support
0 commit comments