介绍
pkg 是一款面向 Node.js 生态的源码打包编译工具,基于 libv8、Node 内核、V8 虚拟机实现,核心作用:将整套 Node.js 项目(代码、依赖、资源)打包为独立可执行文件,支持 Windows/macOS/Linux 三大平台,打包产物无需目标机器预装 Node.js 环境即可直接运行。
底层架构
1. 三部分核心构成
- Node 运行时快照(binary base)
pkg 预先内置对应版本的 Node.js 静态二进制内核(包含 V8 引擎、libuv、内置模块、事件循环、文件 IO 底层接口),打包时以此为基础载体。 - 虚拟文件系统(Snapshot FS)
打包时把项目所有 JS、JSON、静态资源、node_modules 依赖压缩注入二进制内置的虚拟只读文件系统,运行时拦截 Nodefs模块读写请求,重定向读取内置快照资源,而非本地磁盘文件。 - 用户业务代码
项目源码、第三方依赖会被处理、序列化嵌入二进制,运行时由内置 Node 内核从虚拟文件系统加载执行。
2. 打包核心原理
- 预下载对应系统、Node 版本的预编译 Node 基础二进制包;
- 递归解析项目入口文件,通过依赖分析遍历全部导入模块(CommonJS/ESModule 均支持);
- 所有依赖、静态文件序列化压缩,生成资源快照;
- 将快照数据追加到 Node 基础二进制尾部,拼接生成单一可执行程序;
- 程序启动时,先初始化内置 Node 运行时,挂载虚拟文件系统,再读取快照内业务代码执行。
特性
1. 环境隔离
打包产物自带完整 Node 运行时,目标设备无需安装 Node、npm,不存在版本冲突、全局依赖缺失问题。
2. 跨平台构建与分发
- 本地 Windows 可打包出 Linux、macOS 可执行程序,支持一次源码多平台输出;
- 输出格式:Windows
.exe、macOS 可执行二进制、Linux ELF 程序。
3. 代码保护(轻度加密)
源码嵌入二进制快照,不生成明文 JS 文件;虚拟文件系统为只读,普通用户无法直接提取原始源码,适合简单防源码泄露场景(非高强度加密,可被逆向提取字节码)。
4. 资源内嵌能力
支持嵌入图片、配置文件、模板、数据库文件等静态资源,运行时通过 fs 正常读取虚拟路径内文件,无需随程序附带外部资源文件夹。
5. 单文件/目录双输出模式
- 单文件模式:所有运行时、代码、资源合并为单个独立程序,分发便捷;
- 目录模式:运行时内核与资源快照分离存放,启动速度更快,适合大型项目。
适配范围与模块限制
1. 支持模块类型
- Node 内置核心模块(fs、path、http 等);
- 纯 JS 第三方 npm 依赖;
- ESModule、CommonJS 混合项目;
- TypeScript 编译后 JS 代码。
2. 无法完整支持的场景
- 原生 C/C++ 模块(node-gyp 编译包)
原生插件依赖系统动态链接库,无法直接嵌入快照,运行会报错;需单独分发.node插件并手动加载。 - 运行时动态下载/动态 require 未知模块
pkg 打包阶段静态分析依赖,运行时动态拼接路径加载的模块无法提前收录,会出现模块缺失。 - 依赖系统全局动态库、外部系统服务
如依赖系统特定版本 openssl、GPU 驱动、系统软件,打包无法附带系统底层库,跨设备运行易失效。
优缺点
优势
- 部署极简,仅需单个可执行文件,无复杂部署流程;
- 统一运行环境,消除 Node 版本兼容问题;
- 简单源码混淆,避免明文源码直接暴露;
- 支持离线分发,服务器无网络也可部署。
短板
- 打包后文件体积大(内置完整 Node 运行时,通常数十 MB);
- 原生二进制插件兼容性差,处理成本高;
- 存在逆向提取字节码的风险,不能用于高强度商业加密;
- 大型项目打包耗时较长;
- 不支持部分动态代码加载场景,代码编写存在一定约束。
适用场景
- 本地运维工具、CLI 命令行工具封装分发;
- 内网离线 Node 服务,无环境安装权限的服务器;
- 桌面简易脚本工具(搭配 electron 之外的轻量方案);
- 给非技术人员交付 Node 程序,避免配置 Node 环境。
与同类工具核心区别
- vs nexe:二者原理接近,均基于 Node 二进制快照;pkg 生态更成熟、多平台预编译包更完善,社区使用量更高;
- vs electron:electron 附带 Chromium 浏览器内核,用于GUI;pkg 仅 Node 控制台运行时,无图形界面,体积更小;
- vs webpack/rollup:打包工具仅合并 JS 代码,仍依赖外部 Node 环境;pkg 打包完整运行时,输出可独立执行程序。