- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲(Buffer)
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入 Node环境
- 子进程(Child processes)
- 集群(Cluster)
- 命令行选项
- 控制台(Console)
- 核心包(Corepack)
- 加密(Crypto)
- 调试器(Debugger)
- 已弃用的 API
- 诊断通道(Diagnostics Channel)
- 域名系统(DNS)
- 域(Domain)
- 错误(Errors)
- 事件(Events)
- 文件系统(File system)
- 全局变量(Globals)
- HTTP
- HTTP/2
- HTTPS
- 检查器(Inspector)
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:packages 模块
- 网络(Net)
- 系统(OS)
- 路径(Path)
- 性能挂钩(Performance hooks)
- 性能挂钩(Permissions)
- 进程(Process)
- Punycode 国际化域名编码
- 查询字符串(Query strings)
- 命令行库(Readline)
- REPL 交互式编程环境
- 诊断报告
- 单个可执行应用程序
- Stream 流
- 字符串解码器
- 单元测试
- 定时器(Timers)
- 传输层安全/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用程序
- V8
- 虚拟机
- WebAssembly
- Web加密 API(Web Crypto API)
- 网络流 API(Web Streams API)
- 工作线程(Worker threads)
- zlib
Node.js v18.18.2 文档
- Node.js v18.18.2
- ► 目录
-
►
索引
- 断言测试
- 异步上下文跟踪
- 异步钩子
- 缓冲(Buffer)
- C++ 插件
- 使用 Node-API 的 C/C++ 插件
- C++ 嵌入 Node环境
- 子进程(Child processes)
- 集群(Cluster)
- 命令行选项
- 控制台(Console)
- 核心包(Corepack)
- 加密(Crypto)
- 调试器(Debugger)
- 已弃用的 API
- 诊断通道(Diagnostics Channel)
- 域名系统(DNS)
- 域(Domain)
- 错误(Errors)
- 事件(Events)
- 文件系统(File system)
- 全局变量(Globals)
- HTTP
- HTTP/2
- HTTPS
- 检查器(Inspector)
- 国际化
- 模块:CommonJS 模块
- 模块:ECMAScript 模块
- 模块:
node:module
API - 模块:packages 模块
- 网络(Net)
- 系统(OS)
- 路径(Path)
- 性能挂钩(Performance hooks)
- 性能挂钩(Permissions)
- 进程(Process)
- Punycode 国际化域名编码
- 查询字符串(Query strings)
- 命令行库(Readline)
- REPL 交互式编程环境
- 诊断报告
- 单个可执行应用程序
- Stream 流
- 字符串解码器
- 单元测试
- 定时器(Timers)
- 传输层安全/SSL
- 跟踪事件
- TTY
- UDP/数据报
- URL
- 实用程序
- V8
- 虚拟机
- WebAssembly
- Web加密 API(Web Crypto API)
- 网络流 API(Web Streams API)
- 工作线程(Worker threads)
- zlib
- ► 其他版本
- ► 选项
目录
单个可执行应用程序#
源代码: src/node_sea.cc
此功能允许将 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 项目用来检测文件是否已注入的熔断器。--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
fuses字符串,并将最后一个字符翻转为1
以指示资源已注入。
平台支持#
仅在以下平台上定期对 CI 进行单一可执行文件支持测试:
- 视窗
- 苹果系统
- Linux(仅限 AMD64)
这是由于缺乏更好的工具来生成可用于在其他平台上测试此功能的单个可执行文件。
欢迎提出其他资源注入工具/工作流程的建议。请在https://github.com/nodejs/single-executable/discussions发起讨论 ,以帮助我们记录它们。