使用pkg打包Node.js应用的方法步骤

Node.js应用不需要经过编译过程,可以直接把源代码拷贝到部署机上执行,确实比C++、Java这类编译型应用部署方便。然而,Node.js应用执行需要有运行环境,意味着你需要先在部署机器上安装Node.js。虽说没有麻烦到哪里去,但毕竟多了一个步骤,特别是对于离线环境下的部署机,麻烦程度还要上升一级。假设你用Node.js写一些小的桌面级工具软件,部署到客户机上还要先安装Node.js,有点“大炮打蚊子”的感觉。更严重的是,如果部署机器上游多个Node.js应用,而且这些应用要依赖于不同的Node.js版本,那就更难部署了。

理想的情况是将Node.js打包为一个单独的可执行文件,部署的时候直接拷贝过去就行了。除了部署方便外,因为不需要再拷贝源代码了,还有利于保护知识产权。

将Node.js打包为可执行文件的工具有pkg、nexe、node-packer、enclose等,从打包速度、使用便捷程度、功能完整性来说,pkg是最优秀的。这篇文章就来讲一讲半年来我使用pkg打包Node.js应用的一些经验。

pkg的打包原理简单来说,就是将js代码以及相关的资源文件打包到可执行文件中,然后劫持fs里面的一些函数,使它能够读到可执行文件中的代码和资源文件。例如,原来的require(‘./a.js‘)会被劫持到一个虚拟目录require(‘/snapshot/a.js‘)。

安装

pkg既可以全局安装也可以局部安装,推荐采用局部安装:

npm install pkg --save-dev

用法

pkg使用比较简单,执行下pkg -h就可以基本了解用法,基本语法是:

pkg [options] <input>

<input>可以通过三种方式指定:

1.一个脚本文件,例如pkg index.js;
2.package.json,例如pkg package.json,这时会使用package.json中的bin字段作为入口文件;
3.一个目录,例如pkg .,这时会寻找指定目录下的package.json文件,然后在找bin字段作为入口文件。

[options]中可以指定打包的参数:

1.-t指定打包的目标平台和Node版本,如-t node6-win-x64,node6-linux-x64,node6-macos-x64可以同时打包3个平台的可执行程序;
2.-o指定输出可执行文件的名称,但如果用-t指定了多个目标,那么就要用--out-path指定输出的目录;
3.-c指定一个JSON配置文件,用来指定需要额外打包脚本和资源文件,通常使用package.json配置。

项目所在文件夹中缺少package.json文件的情况下:

npm init -f //强迫初始化文件
npm install bluebird --save

使用pkg的最佳实践是:在package.json中的pkg字段中指定打包参数,使用npm scripts来执行打包过程,例如:

{
 ...
 "bin": "./bin/www",
 "scripts": {
  "pkg": "pkg . --out-path=dist/"
 },
 "pkg": {
  "scripts": [...]
  "assets": [...],
  "targets": [...]
 },
 ...
}

scripts和assets用来配置未打包进可执行文件的脚本和资源文件,文件路径可以使用glob通配符。这里就浮现出一个问题:为什么有的脚本和资源文件打包不进去呢?

要回答这个问题,就涉及到pkg打包文件的机制。按照pkg文档的说法,pkg只会自动地打包相对于__dirname、__filename的文件,例如path.join(__dirname, ‘../path/to/asset‘)。至于require(),因为require本身就是相对于__dirname的,所以能够自动打包。假设文件中有以下代码:

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

这些路径都不是常量,pkg没办法帮你自动识别要打包哪个文件,所以文件就丢失了,所以这时候就使用scripts和assets来告诉pkg,这些文件要打包进去。那么我们怎么知道哪些文件没有被打包呢?难倒要一行行地去翻源代码吗?其实很简单,只需要把打包好的文件运行下,报错信息一般就会告诉你缺失哪些文件,并且pkg在打包过程中也会提示一些它不能自动打包的文件。

注意事项

如果说pkg还有哪儿还可以改进的地方,那就是无法自动打包二进制模块*.node文件。如果你的项目中引用了二进制模块,如sqlite3,那么你需要手动地将*.node文件复制到可执行文件同一目录,我通常使用命令cp node_modules/**/*.node .一键完成。但是,如果你要跨平台打包,例如在windows上打包linux版本,相应的二进制模块也要换成linux版本,通常需要你手动的下载或者编译。

那为什么pkg不能将二进制模块打包进去呢?我猜想是require载入一个js文件和node文件,它们的机制是不一样的。另外从设计来说,不自动打包二进制模块也是合理的,因为二进制模块都是平台相关的。如果我在windows上生成一个linux文件,那么就需要拉取linux版本的.node文件,这是比较困难的。并且有些二进制模块不提供预编译版本,需要安装的时候编译,pkg再牛也不可能模拟一个其他平台的编译环境吧。nexe可以自动打包二进制模块,但是只能打包当前平台和当前版本的可执行文件。这意味着如果Node.js应用引用了二进制包,那么这个应用就不能跨平台打包了,所以我认为这方面,nexe不能算是一个好的设计。

还有一点就是关于项目中的配置文件处理,比如数据库连接参数、环境变量等。因为这些配置文件会跟着不同的部署环境进行更改,所以为了方便更改,一般不希望把配置文件打包到exe。为了避免pkg自动地将配置文件打包到exe中,代码中不要采用以下方式读取配置文件:

fs.readFile(path.join(__dirname, ‘./config.json‘)), callback)

而是采用相对于process.CWD()的方法读取:

fs.readFile(path.join(process.CWD(), ‘./config.json‘), callback)
// 或者
fs.readFile(‘./config.json‘, callback)

如果配置文件是js格式的,那么不要直接require(‘./config‘),而是采用动态require:

const config = require(process.CWD() + ‘./config‘)

另外要提及的是pkg打包之后动态载入js文件会有安全性问题,即用户可以在js文件写任何处理逻辑,注入到打包后的exe中。例如,可以读取exe里面的虚拟文件系统,把源代码导出来。所以,尽量不要采用JS作为配置文件,也不要动态载入js模块。

原文地址:https://www.cnblogs.com/caiyt/p/10165776.html

时间: 2024-08-01 21:06:51

使用pkg打包Node.js应用的方法步骤的相关文章

学习 Node.js 的 6 个步骤

学习 Node.js 的 6 个步骤 从刚接触Node.js到现在,自己也是一路摸滚打爬过来的,虽不说是什么高手,但对于如何学习Node.js,还是有一些个人见解,拿出来与大家共勉~ 学习Node.js大致有 6 个步骤或者说 6 个层次: 第一步 对于刚接触Node.js的新手来说,第一步无非是打好基础,你需要弄明白以下事情: JavaScript 的特性和语法.假如你对 JavaScript 还不熟悉的话,推荐书籍及链接: JavaScript 推荐书籍列表 深入理解JavaScript系列

Node.js常用express方法

Node.js 手册查询-Express 方法 1.send方法 send 方法向浏览器发送一个响应信息,并可以智能处理不同类型的数据 send方法在输出响应时会自动进行一些设置,比如HEAD信息.HTTP缓存支持等等 类型可以是: String, Array, Object, Number. 当参数为一个String时,Content-Type默认设置为"text/html" 当参数为Array或Object时,Express会返回一个JSON 当参数为一个NumberExpress

Nginx 配置HTTPS 与Node.js 配置HTTPS方法

前段时间公司网站要求加上HTTPS安全CA证书,公司服务器全是阿里云服务器,并且配有负载均衡,所以选择直接在阿里云购买CA证书,阿里云有一种证书可以免费试用一年,决定申请此证书,阿里云证书需要验证,阿里云有详细教程 配置之后发现所有在HTTPS访问的网站下的所有连接都需要是HTTPS访问,所以还是需要自己进行配置 配置方案记录一下,方便以后自己配置查找 环境 Centos6.8  Nginx  yum安装 首先要将下载的CA证书上传到服务器上面 , 然后打开/etc/nginx/conf.d/自

node.js安装和使用步骤-windows

PS: NODEJS:https://nodejs.org NPM:https://www.npmjs.com/ 一.node.js安装与配置 到https://nodejs.org/en/download/下载,分x64和x86 安装后,配置PATH(F:\Program Files (x86)\nodejs;)和NODE_PATH(F:\Program Files (x86)\nodejs\node_modules;) 二.安装NVM,版本切换管理工具 1.系统创建放NVM代码:(c:\gi

【Node.js】1.安装步骤

1.在官网找到对应版本下载 2.点击安装 3.检查安装成功 path可以看到node.js的安装目录已经自动配置在环境变量path中了 如果node -v或者node --version不能正确展示当前的版本的话,那就需要用户自己去手动的将node.js的安装路径配置到path变量下. 4.安装完成

window下安装nvm、node.js、npm的步骤

1.下载nvm(nodejs版本管理工具) https://github.com/coreybutler/nvm-windows/releases 下载nvm-noinstall.zip,解压即可使用 2.双击install.cmd,直接回车,默认在c盘生成settings.txt 3.配置settings.txt root:E:\front_end\nvm //nvm.exe所在目录 path:E:\front_end\nodejs //node快捷方式所在的路径 arch: 64 //当前系

TODO:Node.js pm2使用方法

pm2 是一个带有负载均衡功能的Node应用的进程管理器. 当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的. 1.使用 npm install pm2 -g 安装 pm2 2.使用pm2管理 Node 进程,执行以下命令启动 node 服务: pm2 start process.json 错误日志输出,less ~/.pm2/logs/video-error.log,Node Error: Cannot find module 'expre

Node.js 的第一个 demo 和本地服务器配置

安装nodejs这里就不叙述了,直接上nodejs官网下载就好了,初学者建议直接下载安装版,无需自己去编译.nodejs安装版和安装其他软件一样,无门槛. 安装nodejs后启动node.js,会打开一个类似黑色的系统命令框,这里是直接输入js代码的命令框,因此在这里输入 node -v 会提示你没有 node 这个命令,如: 如果你想安装其他的包,如 express 等,就需要在开始菜单里面找到 Node.js command prompt 或者 直接运行 cmd 进入命令行. 进入命令行后,

【node.js】模块系统、函数

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统. 一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码.JSON 或者编译过的C/C++ 扩展. 创建模块 在 Node.js 中,创建一个模块非常简单,如下我们创建一个 'hello.js' 文件,代码如下: var hello = require('./hello'); hello.world(); 以上实例中,代码 require('./hello') 引入了当前目录下的hello.