Nodejs使用pkg的官方文档翻译

什么是pkg

这个命令行界面可以将你的Node.js项目打包成可执行文件,即使在没有安装Node.js的设备上也可以运行。
英文文档

使用场景:

  • 创建商业版本的应用程序,而无需提供源代码
  • 创建演示/评估/试用版本的应用程序,而无需提供源代码
  • 快速生成其他平台的可执行文件(交叉编译)
  • 创建一种自解压归档或安装程序
  • 无需安装Node.js和npm即可运行打包的应用程序
  • 无需通过npm install下载数百个文件来部署应用程序。将其作为单个文件部署
  • 将资源文件放入可执行文件中,使其更加便携
  • 在不安装新版本的Node.js的情况下测试你的应用程序

这些功能使得pkg成为将Node.js应用程序打包成可执行文件的有用工具,适用于各种使用场景。

用法

npm install -g pkg
安装完成后,运行pkg --help命令(无参数)以查看选项列表:

pkg [options] <input>

选项:

-h, --help           输出使用信息
-v, --version        输出pkg版本
-t, --targets        逗号分隔的目标列表(参见示例)
-c, --config         package.json或任何包含顶级配置的json文件
--options            将v8选项嵌入可执行文件中以在其中运行
-o, --output         输出文件名或多个文件的模板
--out-path           保存输出的路径,可以是一个或多个可执行文件
-d, --debug          在打包过程中显示更多信息 [关闭]
-b, --build          不下载预构建的基本二进制文件,而是构建它们
--public             加快速度并公开顶级项目的源代码
--public-packages    强制指定的包被视为公开
--no-bytecode        跳过字节码生成,将源文件作为普通js文件包含
--no-native-build    跳过本机插件的构建
--no-signature       在macos上跳过最终可执行文件的签名
--no-dict            逗号分隔的要忽略字典的包名称列表。使用--no-dict *来禁用所有字典
-C, --compress       [默认=None] 压缩算法 = Brotli或GZip

示例:

- 为Linux、macOS和Windows生成可执行文件
 $ pkg index.js
- 使用当前工作目录中的package.json并遵循'bin'条目
 $ pkg .
- 为特定目标机器生成可执行文件
 $ pkg -t node16-win-arm64 index.js
- 为您选择的目标机器生成可执行文件
 $ pkg -t node16-linux,node18-linux,node16-win index.js
- 将'--expose-gc''--max-heap-size=34'嵌入可执行文件中
 $ pkg --options "expose-gc,max-heap-size=34" index.js
- 将packageA和packageB视为公开
 $ pkg --public-packages "packageA,packageB" index.js
- 将所有包视为公开
 $ pkg --public-packages "*" index.js
- 将'--expose-gc'嵌入可执行文件中
 $ pkg --options expose-gc index.js
- 使用GZip减小可执行文件中打包的数据的大小
 $ pkg --compress GZip index.js

你的项目的入口点是一个必需的命令行参数。它可以是:

  • 入口文件的路径。假设它是 /path/app.js,那么打包后的应用程序将与 node /path/app.js 的方式相同。
  • package.json 的路径。pkg 将遵循指定 package.json 的 bin 属性,并将其用作入口文件。
  • 目录的路径。pkg 将在指定的目录中查找 package.json。参见上面的说明。

Targets

pkg可以同时为多个目标机器生成可执行文件。你可以通过--targets选项指定一个逗号分隔的目标列表。一个规范的目标由3个元素组成,用破折号分隔,例如node18-macos-x64node14-linux-arm64

  • nodeRangenode8)、node10node12node14node16latest
  • platformalpinelinuxlinuxstaticwinmacosfreebsd
  • archx64arm64armv6armv7

你可以省略任何元素(例如只指定node14)。省略的元素将从当前平台或系统范围的Node.js安装中获取(其版本和架构)。还有一个别名host,表示所有3个元素都来自当前平台/Node.js。默认情况下,目标是当前Node.js版本和架构的linuxmacoswin

如果你想为不同的架构生成可执行文件,请注意,默认情况下,pkg必须运行目标架构的可执行文件来生成字节码:

  • Linux:使用QEMU配置binfmt。
  • macOS:可以使用Rosetta 2在arm64上构建x64,但反之则不行。
  • Windows:可以使用x64仿真在arm64上构建x64,但反之则不行。

或者,使用--no-bytecode --public-packages "*" --public禁用字节码生成。

macos-arm64是实验性的。请注意强制的代码签名要求。最终的可执行文件必须使用macOS的codesign工具(或Linux上的ldid工具)进行签名(ad-hoc签名就足够了)。否则,可执行文件将被内核终止,最终用户无法允许其运行。pkg会尝试对最终的可执行文件进行ad-hoc签名。如果需要,你可以用你自己的可信任的Apple Developer ID替换这个签名。

为了能够为所有支持的架构和平台生成可执行文件,请在配置了binfmt(QEMU仿真)和安装了ldid的Linux主机上运行pkg

Config

在打包过程中,pkg会解析你的源代码,检测到require调用,遍历你的项目的依赖项,并将它们包含到可执行文件中。在大多数情况下,你不需要手动指定任何内容。

然而,你的代码可能会有require(variable)调用(即所谓的非字面量参数传递给require),或者使用非JavaScript文件(例如视图、CSS、图像等)。

require('./build/' + cmd + '.js');
path.join(__dirname, 'views/' + viewName);

这些情况下,pkg无法处理。因此,你必须在package.json文件的pkg属性中手动指定文件 - 脚本和资源。

"pkg": {
  "scripts": "build/**/*.js",
  "assets": "views/**/*",
  "targets": [ "node14-linux-arm64" ],
  "outputPath": "dist"
}

上面的示例将包含assets/目录中的所有内容,以及build/目录中的所有.js文件,仅为node14-linux-arm64构建,并将可执行文件放置在dist/目录中。

你还可以指定多个glob模式的数组:

"assets": [ "assets/**/*", "images/**/*" ]

只需确保调用pkg package.jsonpkg .以使用package.json的配置。

Scripts

scripts是一个glob模式或glob模式列表。指定为脚本的文件将使用v8::ScriptCompiler进行编译,并将其作为没有源代码的内容放入可执行文件中。它们必须符合你所目标的Node.js版本的JS标准(参见Targets),即已经进行了转译。

Assets

assets是一个glob模式或glob模式列表。指定为资源的文件将作为原始内容打包到可执行文件中,不进行修改。JavaScript文件也可以指定为资源。它们的源代码不会被剥离,这样可以提高文件的执行性能并简化调试过程。

另请参阅在源代码中检测资源和快照文件系统。

Options

Node.js应用程序可以使用运行时选项(属于Node.js或V8)进行调用。要列出这些选项,请输入node --helpnode --v8-options

你可以将这些运行时选项"烘焙"到打包的应用程序中。应用程序将始终以打开这些选项的方式运行。只需删除选项名称前面的--即可。

你可以通过将它们连接在一个字符串中,用逗号(,)分隔,来指定多个选项:

pkg app.js --options expose-gc
pkg app.js --options max_old_space_size=4096
pkg app.js --options max-old-space-size=1024,tls-min-v1.0,expose-gc

Output

如果你只创建一个可执行文件,可以指定--output选项,如果要为多个目标生成可执行文件,则可以指定--out-path选项来指定输出路径。

Debug

通过在pkg命令后添加--debug参数,可以获取打包过程的日志。如果你在某个特定文件上遇到问题(似乎没有被打包到可执行文件中),查看日志可能会有帮助。

Bytecode(可复现性)

默认情况下,你的源代码在写入输出文件之前会被预编译为v8字节码。要禁用此功能,请在pkg命令中添加--no-bytecode参数。

为什么要这样做?
如果你需要一个可复现的构建过程,使得你的可执行文件的哈希值(例如md5、sha1、sha256等)在构建之间保持相同的值。因为编译字节码不是确定性的(参见这里或这里),它会导致具有不同哈希值的可执行文件。禁用字节码编译可以确保给定的输入始终具有相同的输出。

为什么不要这样做?
尽管编译为字节码不能使你的源代码100%安全,但它确实为你的源代码增加了一层小的安全性/隐私性/混淆性。关闭字节码编译会导致原始源代码直接写入可执行文件。如果你在*nix机器上,并且想要一个示例,请使用--no-bytecode标志运行pkg,然后使用GNU strings工具对输出进行处理。然后,你应该能够使用grep命令搜索你的源代码。

其他注意事项
指定--no-bytecode选项将在项目中存在任何未在其package.json中的许可证中明确标记为公共的软件包时失败。默认情况下,pkg将检查每个软件包的许可证,并确保不面向公众的内容只作为字节码包含在内。

如果你确实需要为其他架构构建pkg二进制文件,并且依赖于package.json中具有损坏许可证的软件包,你可以通过使用--public-packages "packageA,packageB"显式地将软件包列入公共白名单,或者使用--public-packages "*"将所有软件包设置为公共来覆盖此行为。

Build

pkg有所谓的“基本二进制文件” - 实际上它们是相同的Node.js可执行文件,但应用了一些补丁。它们被用作pkg创建的每个可执行文件的基础。在打包应用程序之前,pkg会下载预编译的基本二进制文件。如果你希望从源代码编译基本二进制文件而不是下载它们,可以在pkg命令中添加--build选项。首先确保你的计算机符合编译原始Node.js的要求:BUILDING.md

有关更多信息,请参阅pkg-fetch

Compression

通过在pkg命令中添加--compress Brotli--compress GZip参数,可以进一步压缩嵌入在可执行文件中的文件内容。

此选项可以将嵌入式文件系统的大小减小多达60%。

应用程序的启动时间可能会略微缩短。

-C可以用作--compress的快捷方式。

Environment

变量描述
PKG_CACHE_PATH用于指定自定义路径以存储Node.js二进制文件的缓存文件夹。默认值为~/.pkg-cache
PKG_IGNORE_TAG允许忽略与pkg-fetch版本匹配的PKG_CACHE_PATH中创建的附加文件夹
MAKE_JOB_COUNT允许配置用于编译的进程数

示例:

# 1 - 使用export
export PKG_CACHE_PATH=/my/cache
pkg app.js

# 2 - 在脚本之前传递
PKG_CACHE_PATH=/my/cache pkg app.js

Usage of packaged app

通过命令行调用打包的应用程序./app a b等同于node app.js a b

Snapshot filesystem

在打包过程中,pkg会收集项目文件并将它们放入可执行文件中。这被称为快照。在运行时,打包的应用程序可以访问快照文件系统,其中包含所有这些文件。

打包的文件在其路径中具有/snapshot/前缀(在Windows中为C:\snapshot\)。如果你使用了pkg /path/app.js命令行,那么在运行时,__filename的值可能是/snapshot/path/app.js__dirname也将是/snapshot/path。下面是路径相关值的比较表:

在Node中的值打包后的值注释
__filename/project/app.js/snapshot/project/app.js
__dirname/project/snapshot/project
process.cwd()/project/deploy假设应用程序被调用在/deploy目录下
process.execPath/usr/bin/nodejs/deploy/app-x64/deploy目录下运行的app-x64
process.argv[0]/usr/bin/nodejs/deploy/app-x64
process.argv[1]/project/app.js/snapshot/project/app.js
process.pkg.entrypointundefined/snapshot/project/app.js
process.pkg.defaultEntrypointundefined/snapshot/project/app.js
require.main.filename/project/app.js/snapshot/project/app.js

因此,为了使用在打包时收集的文件(require一个JavaScript文件或提供一个资源),你应该将__filename__dirnameprocess.pkg.defaultEntrypointrequire.main.filename作为路径计算的基础。对于JavaScript文件,你可以直接使用requirerequire.resolve,因为它们默认使用当前的__dirname。对于资源,请使用path.join(__dirname, '../path/to/asset')。了解更多关于path.join的信息,请参阅在源代码中检测资源。

另一方面,为了在运行时访问真实的文件系统(获取用户的外部JavaScript插件、JSON配置甚至获取用户目录列表),你应该使用process.cwd()path.dirname(process.execPath)

在源代码中检测资源

pkg遇到path.join(__dirname, '../path/to/asset')时,它会自动将指定的文件打包为资源。请注意,path.join必须有两个参数,最后一个参数必须是字符串字面量。

这样,你甚至可以避免为你的项目创建pkg配置。

原生插件

原生插件(.node文件)的使用是支持的。当pkgrequire调用中遇到一个.node文件时,它会将其打包为资源。在某些情况下(比如使用bindings包),模块路径是动态生成的,pkg无法检测到它。在这种情况下,你应该直接将.node文件添加到package.json中的assets字段中。

Node.js加载原生插件的方式与经典的JS文件不同。它需要在磁盘上有一个文件来加载它,但是pkg只生成一个文件。为了解决这个问题,pkg会在磁盘上创建一个临时文件。这些文件会在进程退出后保留在磁盘上,并在下次进程启动时再次使用。

当安装包含原生模块的包时,原生模块会根据当前系统范围的Node.js版本进行编译。然后,当你使用pkg编译你的项目时,注意使用--target选项。你应该指定与系统范围的Node.js版本相同的Node.js版本,以使编译后的可执行文件与.node文件兼容。

请注意,完全静态的Node二进制文件无法加载原生绑定,因此你不能在linuxstatic上使用Node绑定。

API

const { exec } = require('pkg')

exec(args)

exec函数接受一个命令行参数的数组,并返回一个Promise。它可以用来从JavaScript文件构建可执行文件。例如:

await exec(['app.js', '--target', 'host', '--output', 'app.exe']);
// 对app.exe进行操作,运行、测试、上传、部署等等

故障排除

  • 错误:ENOENT: no such file or directory, uv_chdir:当应用程序运行时删除了运行目录,或者通常情况下删除了process.cwd()目录时会出现此错误。请确保在运行应用程序之前目录存在。

  • 错误:ERR_INSPECTOR_NOT_AVAILABLE:当使用NODE_OPTIONS变量强制启用调试模式运行Node.js时会出现此错误。由于pkg可执行文件通常用于生产环境,因此不允许使用调试选项。如果确实需要使用调试器,可以自己构建一个可调试的Node.js。

  • 错误:require(…).internalModuleStat is not a function:当使用NODE_OPTIONS变量与一些引导或节点选项导致与pkg冲突时,会出现此错误。一些IDE(如VS Code)可能会自动添加此环境变量。

你可以在Unix系统(Linux/macOS)的bash中进行检查:

$ printenv | grep NODE

高级

在构建可执行文件时使用--debug标志时,pkg会在应用程序启动时提供显示虚拟文件系统和符号链接表内容的能力,前提是设置了环境变量DEBUG_PKG。这个功能可以用来检查符号链接是否被正确处理,并检查所有应用程序所需的文件是否正确地合并到最终的可执行文件中。

$ pkg --debug app.js -o output
$ DEBUG_PKG=1 output

或者在Windows系统的命令提示符中:

C:\> pkg --debug app.js -o output.exe
C:\> set DEBUG_PKG=1
C:\> output.exe

注意:在生产环境中不要使用--debug标志。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wusp1994

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值