使用pkg编译打包nodejs程序成执行文件

NodeJS学习使用过的童鞋们都知道,可以利用V8来解析运行javascript程序, 我们在写一个server(一般都是使用NodeJS建立http/https server), 如果是云平台,都会直接把js代码上传上去,因为云平台的账户都是自己的,那么客户端的用户是看不见server的code的,那么我们一般的应用server呢?比如你需要把程序安装在客户那边的时候,你的javascript code需要保密吧?同时为了运行javascript代码,我们需要安装node, 而node程序有很多版本,怎么跟其它软件统一版本呢?最好是既不能暴露源代码,有能不要安装其他的程序比如node, 那么pkg就是其中的一个选择,它将所有的js code编译成二进制, 并且直接把node的code打包进去,形成一个exe, 直接双击运行,不需要安装node,那么客户机器上安装的Node版本就跟咱们的server无关了。

在使用pkg进行编译的时候,使用起来简单,但是编译的时候有一些注意的地方:

1. 如果有native addon的话,pkg不支持将addon (.node文件)打包进exe, 所以如果自己写的.node文件或者引用的module里面有.node文件,需要打包完之后将.node文件放到跟exe一个目录里面。

2. 检查资源的时候,pkg在打包的时候,要对目录进行判断,比如require(路径)或者path.join(路径)。但是对于一些特殊引用例如:

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

在例子中,cmd和viewName都是参数,也就是在pkg打包的时候,并不知道真是的文件名字,pkg就没法把文件或者资源打包,这种情况下就可以在package.json的配置里面增加assets的配置

"pkg": {
    "scripts": "build/**/*.js",
    "assets": "views/**/*"
  }

其中assets的文件就会对应路径一起打包进去。如果是多个目录那就可以是数组,如下:

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

下面是对package.json里面的'pkg'的说明:

Scripts

scripts is a glob or list of globs. Files specified as scripts will be compiled using v8::ScriptCompiler and placed into executable without sources. They must conform to the JS standards of those Node.js versions you target (see Targets), i.e. be already transpiled.

指定的files将会编译到exe里面,但是这个js文件必须要符合目标版本的标准,比如你要编译成node的12版本,windows下的应用程序,那么你用的js语法必须被这个版本的node支持

Assets

assets is a glob or list of globs. Files specified as assets will be packaged into executable as raw content without modifications. Javascript files may also be specified as assets. Their sources will not be stripped as it improves execution performance of the files and simplifies debugging.

assets里面指定的文件,将会原封不动的打包进去,即使是javascript file 作为assets

3. 如果我们的application 有配置文件,需要在安装的时候配置怎么办呢?那可以不打包配置文件,例如我们经常用的config模块,config模块如果不指定配置文件,需要在project目录下创建config目录,在文件夹下创建default.json文件,在里面做一些配置,在安装完application之后,可以修改这些配置,如果打包进exe,那就没法修改了,这种情况下,不要把该文件default.json放到配置的assets里面,只是将该文件以及对应的目录放到跟exe同一个目录下就行,比如:本例中将打包的demo.exe和config文件夹在同一个文件夹里面。

当然对于config模块是因为内部读配置文件的时候,用到了

Path.join( process.cwd(), 'config')

这就涉及到在打包前和打包后,目录的对比了,这就是snapshot文件系统,打包后的所有的文件都有个/snapshot(如果目标文件是windows的exe就是c:/snapshot)的前缀文件夹,比如打包的时候用

pkg  /path/app.js

那么打包后,__filename就是/snapshot/path/app.js,__dirname就是/snapshot/path,下面是列的表格。

value with node packaged comments
__filename /project/app.js /snapshot/project/app.js  
__dirname /project /snapshot/project  
process.cwd() /project /deploy suppose the app is called ...
process.execPath /usr/bin/nodejs /deploy/app-x64 app-x64 and run in /deploy
process.argv[0] /usr/bin/nodejs /deploy/app-x64  
process.argv[1] /project/app.js /snapshot/project/app.js  
process.pkg.entrypoint undefined /snapshot/project/app.js  
process.pkg.defaultEntrypoint undefined /snapshot/project/app.js  
require.main.filename /project/app.js /snapshot/project/app.js  

所以通过上面可以看出,如果你想将配置文件放到外面,那么在读取配置文件的时候,要使用path.join(process.cwd(), 配置文件相对路径),因为通过上面的表格可以看出来process.cwd()是exe所在的目录。

注意: 因为native addon 是跟编译的时候node版本是有关系的,那么我们在用pkg进行打包的时候,target要对应。

4. 如果你是用typescript编写的程序,那么在进行打包之前,需要用tsc进行compile到javascript,然后再打包。

下面是一个简单的例子:

a. 在package.json里面增加配置:

  "bin": "dist/app.js",
  "pkg": {
    "scripts": "dist/**/*.js",
    "assets": [
      "package.json"
    ]
  },

b. 安装pkg,   npm install -g pkg

c. 在package.json的所在文件夹里运行 pkg . -t node12-win

这样就package.json所在的文件夹就会出现一个exe,名字是通过package.json里面的'name'来设置的。

pkg路径

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(使用pkg编译打包nodejs程序成执行文件)