- 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 v18.16.0 文档
- Node.js v18.16.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 通过允许将 JavaScript 文件注入 node
二进制文件来支持 单个可执行应用程序 的创建。 在启动过程中,程序会检查是否注入了任何东西。 如果找到脚本,它将执行其内容。 否则 Node.js 会像往常一样运行。
单个可执行应用程序功能仅支持运行单个嵌入式 CommonJS 文件。
可以使用任何可以将资源注入 node
二进制文件的工具将捆绑的 JavaScript 文件转换为单个可执行应用程序。
以下是使用此类工具 postject 创建单个可执行应用程序的步骤:
-
创建一个 JavaScript 文件:
$ echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
-
创建
node
可执行文件的副本并根据需要命名:$ cp $(command -v node) hello
-
通过使用以下选项运行
postject
,将 JavaScript 文件注入到复制的二进制文件中:hello
- 在步骤 2 中创建的node
可执行文件副本的名称。NODE_JS_CODE
- 二进制文件中将存储 JavaScript 文件内容的资源/注释/部分的名称。hello.js
- 在步骤 1 中创建的 JavaScript 文件的名称。--sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2
- Node.js 项目用来检测文件是否被注入的 fuse。--macho-segment-name NODE_JS
(仅在 macOS 上需要)- 将存储 JavaScript 文件内容的二进制文件中的段的名称。
总而言之,这是每个平台所需的命令:
-
在 macOS 以外的系统上:
$ npx postject hello NODE_JS_CODE hello.js \ --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2
-
在 macOS 上:
$ npx postject hello NODE_JS_CODE hello.js \ --sentinel-fuse NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \ --macho-segment-name NODE_JS
-
运行二进制文件:
$ ./hello world Hello, world!
注意事项#
注入模块中的 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 应用程序的工具必须将 JavaScript 文件的内容注入到:
- 如果
node
二进制文件是 PE 文件,则名为NODE_JS_CODE
的资源 - 如果
node
二进制文件是 Mach-O 文件,则NODE_JS
段中名为NODE_JS_CODE
的部分 - 如果
node
二进制文件是 ELF 文件,则名为NODE_JS_CODE
的注释
在二进制文件中搜索 NODE_JS_FUSE_fce680ab2cc467b6e072b8b5df1996b2:0
fuse 字符串并将最后一个字符翻转为 1
以指示已注入资源。
平台支持#
仅在以下平台上的 CI 上定期测试单一可执行支持:
- Windows
- 苹果系统
- Linux(仅限 AMD64)
这是由于缺乏更好的工具来生成可用于在其他平台上测试此功能的单一可执行文件。
欢迎对其他资源注入工具/工作流程提出建议。 请在 https://github.com/nodejs/single-executable/discussions 开始讨论以帮助我们记录它们。