- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS模块
- module/esm ECMAScript模块
- module/package 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
Node.js v20.2.0 文档
- Node.js v20.2.0
- ► 目录
-
►
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS模块
- module/esm ECMAScript模块
- module/package 包模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- stream 流
- stream/web 网络流
- string_decoder 字符串解码器
- test 测试
- timers 定时器
- tls 安全传输层
- trace_events 跟踪事件
- tty 终端
- url 网址
- util 实用工具
- v8 引擎
- vm 虚拟机
- wasi 网络汇编系统接口
- worker_threads 工作线程
- zlib 压缩
- ► 其他版本
- 云服务器
目录
单个可执行应用程序#
源代码: lib/internal/main/single_executable_application.js
此功能允许将 Node.js 应用程序方便地分发到未安装 Node.js 的系统。
Node.js 通过允许将由 Node.js 准备的 blob 注入 node
二进制文件来支持 单个可执行应用程序 的创建,其中可以包含捆绑脚本。 在启动过程中,程序会检查是否注入了任何东西。 如果找到 blob,它会执行 blob 中的脚本。 否则 Node.js 会像往常一样运行。
单个可执行应用程序功能目前仅支持使用 CommonJS 模块系统运行单个嵌入式脚本。
用户可以使用 node
二进制文件本身和任何可以将资源注入二进制文件的工具从他们的捆绑脚本创建单个可执行应用程序。
以下是使用此类工具 postject 创建单个可执行应用程序的步骤:
-
创建一个 JavaScript 文件:
$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
-
创建一个配置文件,构建一个可以注入单个可执行应用程序的 blob(有关详细信息,请参阅 生成单个可执行准备 blob):
$ echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
-
生成要注入的 blob:
$ node --experimental-sea-config sea-config.json
-
创建
node
可执行文件的副本并根据需要命名:- 在 Windows 以外的系统上:
$ cp $(command -v node) hello
- 在 Windows 上:
使用 PowerShell:
$ cp (Get-Command node).Source hello.exe
使用命令提示符:
$ for /F "tokens=*" %n IN ('where.exe node') DO @(copy "%n" hello.exe)
.exe
扩展名是必需的。 -
删除二进制文件的签名(仅限 macOS 和 Windows):
- 在 macOS 上:
$ codesign --remove-signature hello
- 在 Windows 上(可选):
signtool 可以从已安装的 Windows SDK 使用。 如果跳过此步骤,请忽略来自 postject 的任何与签名相关的警告。
$ signtool remove /s hello.exe
-
通过使用以下选项运行
postject
将 blob 注入到复制的二进制文件中:hello
/hello.exe
- 在步骤 4 中创建的node
可执行文件副本的名称。NODE_SEA_BLOB
- 二进制文件中将存储 blob 内容的资源/注释/部分的名称。sea-prep.blob
- 在步骤 1 中创建的 blob 的名称。--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
- Node.js 项目用来检测文件是否被注入的 fuse。--macho-segment-name NODE_SEA
(仅在 macOS 上需要)- 二进制文件中将存储 blob 内容的段的名称。
总而言之,这是每个平台所需的命令:
-
在 Linux 上:
$ npx postject hello NODE_SEA_BLOB sea-prep.blob \ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
-
在 Windows 上:
$ npx postject hello.exe NODE_SEA_BLOB sea-prep.blob \ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
-
在 macOS 上:
$ npx postject hello NODE_SEA_BLOB sea-prep.blob \ --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \ --macho-segment-name NODE_SEA
-
签署二进制文件(仅限 macOS 和 Windows):
- 在 macOS 上:
$ codesign --sign - hello
- 在 Windows 上(可选):
需要有证书才能工作。 但是,未签名的二进制文件仍然可以运行。
$ signtool sign /fd SHA256 hello.exe
-
运行二进制文件:
- 在 Windows 以外的系统上
$ ./hello world Hello, world!
- 在 Windows 上
$ .\hello.exe world Hello, world!
生成单个可执行准备 blob#
可以使用将用于构建单个可执行文件的 Node.js 二进制文件的 --experimental-sea-config
标志生成注入到应用程序中的单个可执行文件准备 blob。 它采用 JSON 格式的配置文件路径。 如果传递给它的路径不是绝对路径,Node.js 将使用相对于当前工作目录的路径。
该配置当前读取以下顶层字段:
{
"main": "/path/to/bundled/script.js",
"output": "/path/to/write/the/generated/blob.blob",
"disableExperimentalSEAWarning": true // Default: false
}
如果路径不是绝对路径,Node.js 将使用相对于当前工作目录的路径。 用于生成 blob 的 Node.js 二进制文件的版本必须与将注入 blob 的版本相同。
注意事项#
注入模块中的 require(id)
不是基于文件的#
注入模块中的 require()
与未注入模块可用的 require()
不同。 除 require.main
外,它也不具有非注入 require()
所具有的任何属性。 它只能用于加载内置模块。 尝试加载只能在文件系统中找到的模块将引发错误。
用户可以将他们的应用程序捆绑到一个独立的 JavaScript 文件中以注入可执行文件,而不是依赖于基于 require()
的文件。
这也确保了更具确定性的依赖图。
但是,如果仍然需要基于 require()
的文件,也可以实现:
const { createRequire } = require('node:module');
require = createRequire(__filename);
注入模块中的 __filename
和 module.filename
#
注入模块中的 __filename
和 module.filename
的值等于 process.execPath
。
注入模块中的 __dirname
#
注入模块中__dirname
的值等于process.execPath
的目录名。
单个可执行应用程序创建过程#
旨在创建单个可执行 Node.js 应用程序的工具必须将使用 --experimental-sea-config"
准备的 blob 的内容注入到:
- 如果
node
二进制文件是 PE 文件,则名为NODE_SEA_BLOB
的资源 - 如果
node
二进制文件是 Mach-O 文件,则NODE_SEA
段中名为NODE_SEA_BLOB
的部分 - 如果
node
二进制文件是 ELF 文件,则名为NODE_SEA_BLOB
的注释
在二进制文件中搜索 NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2:0
fuse 字符串并将最后一个字符翻转为 1
以指示已注入资源。
平台支持#
仅在以下平台上的 CI 上定期测试单一可执行支持:
- Windows
- 苹果系统
- Linux(除 Alpine 之外的所有发行版 由 Node.js 支持 和除 s390x 和 ppc64 之外的所有架构 由 Node.js 支持)
这是由于缺乏更好的工具来生成可用于在其他平台上测试此功能的单一可执行文件。
欢迎对其他资源注入工具/工作流程提出建议。 请在 https://github.com/nodejs/single-executable/discussions 开始讨论以帮助我们记录它们。