前言
最近在研发基于electron的桌面应用,其中涉及到外设交互部分需要使用dll实现,在经历了艰难的环境配置之后,最后由于electron内存管理问题导致应用崩溃使得electron+ffi实现动态链接库调用这条路无法走通。当时还剩下两种方案可以尝试:
- 自己创建dll封装原生dll调用,感觉成功几率很低。
- 写node addons编译成node插件,需要较强c++功底,难度较大,且最后成功概率不高。
为什么坚持了两个星期还不放弃是因为node+ffi这条路已经走通了,证明第三方的dll是没有问题的。所以试着能不能解决electron中出现的问题。
当electron不能实现的事实逐渐明朗,我开始转移方向。首先想到的是nwjs+ffi的方案,随后迅速想到为什么不使用node自己实现呢?将此部分功能单独分割成为第三方应用,通过某种通信方式实现(写缓存、数据库、http等)。最不济的情况是我为每台终端部署node服务(此应用是B2B,需要实施,不需要自己安装,这一点帮了大忙)
最好的方式是不需要安装node等一堆东西,直接是可执行文件。因此我开始寻找node打包成可执行文件的方法。
为什么要将node应用打包成可执行文件
- 部署方便,给客户演示和生产环境部署都很方便
- 保护源代码(很有用)
- 宿主机器其他应用对node版本可能有不同的要求
- 测试应用在不同node版本下兼容性
pkg打包的使用方法
将Node.js打包为可执行文件的工具有pkg、nexe、node-packer、enclose等,从打包速度、使用便捷程度、功能完整性来说,pkg是最优秀的。
安装
推荐采用局部安装
1 | npm install pkg -D |
用法
1 | $ pkg -h |
项目的入口点是强制CLI参数。它可能是:
- 输入文件的路径
- package.json ,pkg会去寻找bin属性作为入口文件
- 路径是一个目录地址,pkg会在目录下寻找package.json文件,然后如上
targets
pkg能同时为多个平台打包。使用-t 选项,定义由三部分组成,如node6-macos-x64:
- nodeRange node${n} or latest
- platform freebsd, linux, alpine, macos, win
- arch x64, x86, armv6, armv7
native addons
如果说pkg还有哪儿还可以改进的地方,那就是无法自动打包二进制模块*.node文件。如果你的项目中引用了二进制模块,如sqlite3,那么你需要手动地将*.node文件复制到可执行文件同一目录,我通常使用命令cp node_modules/**/*.node .一键完成。但是,如果你要跨平台打包,例如在windows上打包linux版本,相应的二进制模块也要换成linux版本,通常需要你手动的下载或者编译。
后台运行与开机自启动
开机自启动原理就是将exe文件,通过命令注册到开机服务项。
SC Create 创建一个Windows系统服务
描述SC 是用于与服务控制管理器和服务进行通信的命令行程序。
命令行,有一点需要注意,等号和值之间要有空格,否则会报错
1 | sc create test binPath="E:\node\app.exe" start=auto |
可能遇到问题:
第一次打包的时候,会遇到下包很慢很可能超时的问题。到https://github.com/zeit/pkg-fetch/releases
下载对应的包,然后~/.pkg-cache/2.5/目录下,改名为fetched-v8.11.3-macos-x64(参考运行时下的包名字改)即可。
参考https://github.com/zeit/pkg/issues/419
windows 路径一般是用户/username/.pkg-cache
注册为系统服务
当我使用 sc create xx binPath= xx start= auto创建完系统服务后,发现启动报错,大致找了一下。
exe注册成服务了!但是启动服务的时候会报[错误1053:服务没有及时响应启动或控制请求.] ,我想应该是我的exe被服务启动后没有能回复一个服务的消息,不知道要在exe里面做什么样的操作才能不报这样的错误,不是所有的程序都能添加到服务里,要是专问的程序才行,程序里要相应控件,才会有返回值,返回告诉操作系统服务开启情况,QQ程序开发时就不是用来为作为服而设计的,所以不能当服务用
因此参考issues137找到一个nssm的工具,用法很简单。大致罗列一下
第一步:先将程序地址设置到环境变量,就把nssm.exe放到目录下好了。
第二步:nssm install servicename
第三部:按要求配置,注意设置日志输出文件和时间戳
第四步:进入服务列表进行设置,在恢复里面设置第一次失败重启(因为要做开机启动嘛),第二次也重启服务,第三次无操作,千万别设置重启电脑,之前试了一次把硬盘引导分区都破坏了,导致连BIOS都进不去,只好拆下硬盘,用其他电脑PE重做分区,还好是一个新的测试电脑。
