打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
NodeJS打包可执行文件工具Pkg使用心得。
这个项目很神奇,直接将node.js项目打包成windows可以直接执行的exe文件(也支持FreeBSD、linux、macos、arm系统),甚至不需要安装Node.js,且无须修改你项目中的任何代码!
首先安装pkg
npm install -g pkg
然后在项目目录下执行
pkg entrance.js
即可打包linux,macos,win3个平台的可执行文件。entrance.js为你node项目的入口文件。
如果只想打包windows下的exe,则加上-t参数。win即为打包成windows平台下的exe文件,具体可选参数参见项目目录
pkg -t win entrance.js
稍等片刻后项目目录下就会生成打包好的entrance.exe文件。
pkg会自动从入口文件开始查找依赖的文件并全数打包进去,无须修改项目里的任何代码。
例:
其他
pkg可以根据package.json下的配置进行打包,默认入口文件为bin指向的文件。
执行
pkg .
或是
pkg package.json
即可自动按照package.json的配置打包。
//package.json{    //其他配置项
   "bin": "service.js",//入口文件
   "pkg": {        "scripts": [            "build/**/*.js"//需要打包进来的其他js文件,可添加多个
       ],        "assets": [            "dist/**/*"//静态文件的目录,可添加多个
       ]
   }
}    
注意:静态文件需要在项目中将文件的引用换成
path.join(__dirname, 'dist')
的形式,才可以正常打包,否则可能会读取不到。
示例
使用vue-cli建立项目,并使用npm run build将你的项目编译生成静态文件到dist目录下。这些都是vue-cli自带的内容,不再赘述。
在项目目录下新建一个service.js文件,并添加以下代码,在本地起一个express静态服务器,使你能够在本地访问你的网站(部署到线上也是类似)
//service.jsconst express = require('express');const app = express();const path = require('path');

app.use(express.static(path.join(__dirname, 'dist')));//注意这里使用path.join(__dirname, 'dist')而不是'dist',虽然在命令行中执行起来效果是一样的,不过pkg打包会无法识别到dist目录
var server = app.listen(8081, function () {    var host = server.address().address    var port = server.address().port    console.log(`AIbuy agents server start successfully on http://${host}:${port}`)
})
此时你可以在控制台执行
node service.js
来启动你的服务器了,启动完成后,浏览器访问http://localhost:8081/即可查看你的网站。
接下来我们使用将service.js和dist目录打包成一个exe文件,方便他人使用
首先安装pkg
npm install -g pkg
然后修改package.json,添加bin(如果不是service.js的话)和pkg项
{    //其他配置项
   "bin": "service.js",//指定入口文件
   "pkg": {        "assets": [            "dist/**/*"//指定要打包的静态文件目录
       ]
   }
}
然后在项目目录下执行
pkg -t win package.json
完成后即生成一个exe文件,双击启动即相当于执行node service.js,然后你浏览器里就能访问打包好的项目了!跟之前用node启动项目再访问一样,但这时不需要提前安装node了。
但说实话,如果是复杂的项目、大型的项目、有文件读写的项目等,打包这个操作还是有些复杂的,需要考虑不少打包带来的影响,也可能需要修改某些功能代码。如果是用于代码保护目的,防止发布后别人看到自己的程序代码,也可以用JShaman之类的JS代码保护平台对源码进行加密,也是可以保护nodeJS代码的。
下面是一个具体的示例,演示使用pkg打包egg(一个web框架)项目:
1、在egg配置文件中把涉及到写文件的路径都移到包外(pkg的虚拟文件系统只是用来应对读的行为,所有写相关都得移出包外)
// 通过process.cwd()获取当前执行文件执行的路径config.rundir = process.cwd() + '/run';// 配置执行时临时文件的路径config.logger = {
   dir: path.join(process.cwd(), 'logs', logDir),//配置普通日志文件地址
 };  config.customLogger = {
   scheduleLogger: {
     file: path.join(process.cwd(), 'logs', logDir, 'egg-schedule.log'),//配置定时任务日志的地址
   },
 };  config.static = { // 必须把public移出项目,否则在pkg的包中egg的static中间件会有对public操作(确保文件夹),会有抛错
   prefix: '/',
   dir: process.cwd() + '/public',//配置静态文件的地址
 };
2、修改package.json文件
{
   ...


 "bin": "pkg-entry.js", // 执行包的入口文件,可执行包启动的时候默认会调用该文件

 "pkg": {// 以下主要是声明那些文件需要被打包(pkg会解析require中的静态路径,但在egg.js中很多文件都是通过框架引用的,无法依赖解析)
   "scripts": [ // 这里是声明需要打包的js文件,这里的声明的js文件都会被编译为v8字节码(建议主动声明,不要依赖pkg自动引入)
     "./app/**/*.js",      "./config/**/*.js",      "./normalJs/**/*.js", // 不只是egg的文件,只要要用到就要声明打包
     "./app.js",      "./agent.js"
   ],    "assets": [ // 这里是声明需要打包的静态文件(即使有js文件也不进行编译)。
     "./lib/**/*",// lib中是我打算开放的一些egg组件,所有不需要编译
     "./app/public/**/*",// 如果要把前端静态文件打包进来,就直接声明(但是在egg中static中间件会有抛错,需要hack egg或者 hack pkg)
     "./node_modules/**/*"// npm安装的所有依赖包全部打包进来,不要依赖自动引入,很容易导致部分文件没打包,出现各种意料外的错误
   ]
 },
}
3、增加入口文件pkg-entry.js(名字保持和package.json中一致)
const fs = require('fs');// 如果是egg的ts项目,由于egg-script会给ts项目通过-r引入sourcemap的注入文件,但是pkg的spawn不支持,所以把项目标识为飞ts// 如果不是ts项目忽略一下两行const pkgInfo = require('./package');
pkgInfo.egg.typescript = false; // 防止egg-script识别为 typescript 自动添加soucemap支持(--require 在pkg的spawn中不支持)//我自己的工具包的配置文件是直接打包到安装包里面的,这样就不方便修改配置了。于是把提供给运维配置的配置都适用dotenv来配置,以下引入dotenv的预执行脚本//也可以考虑把配置文件放到包外,不过因为包内执行包外js,会增加被攻击的风险require('dotenv/config');// 由于egg-script是默认以当前执行proccess.cwd() 路径为默认项目的,打包后需要每次输入 /snapshot/${项目文件夹名} 作为指定目录// 所以,以下为修改参数,自动嵌入“/snapshot/${项目文件夹名}”const baseDir = '/snapshot/' + fs.readdirSync('/snapshot')[0];console.log('baseDir:', baseDir);// 当 start 的时候,自动嵌入bashDir为 /snapshot/${项目文件夹名}const startIndex = process.argv.indexOf('start');if (startIndex > -1) {
   process.argv = [].concat(
       process.argv.slice(0, startIndex + 1),
       baseDir,
       process.argv.slice(startIndex + 1),
   );
}// 然后直接调起egg-scripts执行require('./node_modules/egg-scripts/bin/egg-scripts.js');
正如前面所说,用pkg打包,可能会有这些修改过程,所以说如果是单纯的防代码泄露是可以用JShaman来完成的。
4、 执行打包
## --targets 用于制定平台和node版本,不指定时默认为3个平台以package.json中的node版本配置为准## --out-path 指定执行包输出文件夹,默认为当前文件夹## --debug 用于调试,可了解哪些文件被打包pkg .  --targets node8-linux-x64 --out-path /usr/dist  --debug
5、运行
> chmod a+x ./appName #给可执行包增加执行权限> ./appName start   # 启动项目,除项目路径其它参数都和egg-scripts一致 可以用--title指定egg服务名>./appName stop # 关闭项目(会关闭当前服务器的所有egg服务,如果有多个,最好用--title来指定要关闭的项目)
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
vue[0x01] -- Hello World
Grunt 新手一日入门 | 于江水
 Grunt Getting started 
grunt 初了解
Python包管理工具setuptools详解
webpack学习(一)安装和基本环境搭建、一次js打包体验及不同版本错误
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服