Package your Node.js project into an executable https://npmjs.com/pkg
This command line interface enables you to package your Node.js project into an executable that can be run even on devices without Node.js installed.
Use Cases
- Make a commercial version of your application without sources
- Make a demo/evaluation/trial version of your app without sources
- Instantly make executables for other platforms (cross-compilation)
- Make some kind of self-extracting archive or installer
- No need to install Node.js and npm to run the packaged application
- No need to download hundreds of files via
npm install
to deployyour application. Deploy it as a single file - Put your assets inside the executable to make it even more portable
- Test your app against new Node.js version without installing it
Usage
npm install -g pkg
After installing it, run pkg --help
without arguments to see list of options.
The entrypoint of your project is a mandatory CLI argument. It may be:
- Path to entry file. Suppose it is
/path/app.js
, thenpackaged app will work the same way asnode /path/app.js
- Path to
package.json
.Pkg
will followbin
property ofthe specifiedpackage.json
and use it as entry file. - Path to directory.
Pkg
will look forpackage.json
inthe specified directory. See above.
Targets
pkg
can generate executables for several target machines at atime. You can specify a comma-separated list of targets via --targets
option. A canonical target consists of 3 elements, separated bydashes, for example node6-macos-x64
or node4-linux-armv6
:
- nodeRange node${n} or latest
- platform freebsd, linux, macos, win
- arch x64, x86, armv6, armv7
You may omit any element (and specify just node6
for example).The omitted elements will be taken from current platform orsystem-wide Node.js installation (it's version and arch).There is also an alias host
, that means that all 3 elementsare taken from current platform/Node.js. By default targets arelinux,macos,win
for current Node.js version and arch.
Config
During packaging process pkg
parses your sources, detectscalls to require
, traverses the dependencies of your projectand includes them into executable. In most cases youdon't need to specify anything manually. However your codemay have require(variable)
calls (so called non-literalargument to require
) or use non-javascript files (forexample views, css, images etc).
require('./build/' + cmd + '.js')
path.join(__dirname, 'views/' + viewName)
Such cases are not handled by pkg
. So you must specify thefiles - scripts and assets - manually in pkg
property ofyour package.json
file.
"pkg": {
"scripts": "build/**/*.js",
"assets": "views/**/*"
}
Just be sure to call pkg package.json
or pkg .
to make useof scripts
and assets
entries.
Scripts
scripts
is a globor list of globs. Files specified as scripts
will be compiledusing v8::ScriptCompiler
and placed into executable withoutsources. They must conform JS standards of those Node.js versionsyou target (see Targets), i.e. be already transpiled.
Assets
assets
is a globor list of globs. Files specified as assets
will be packagedinto executable as raw content without modifications. Javascriptfiles may be specified as assets
as well. Their sources willnot be stripped. It improves performance of execution of thosefiles and simplifies debugging.
See alsoDetecting assets in source code andSnapshot filesystem.
Options
Node.js application can be called with runtime options(belonging to Node.js or V8). To list them type node --help
ornode --v8-options
. You can "bake" these runtime options intopackaged application. The app will always run with the optionsturned on. Just remove --
from option name.
pkg app.js --options expose-gc
Output
You may specify --output
if you create only one executableor --out-path
to place executables for multiple targets.
Debug
Pass --debug
to pkg
to get a log of packaging process.If you have issues with some particular file (seems not packagedinto executable), it may be useful to look through the log.
Build
pkg
has so called "base binaries" - they are actually samenode
executables but with some patches applied. They areused as a base for every executable pkg
creates. pkg
downloads precompiled base binaries before packaging yourapplication. If you prefer to compile base binaries fromsource instead of downloading them, you may pass --build
option to pkg
. First ensure your computer meets therequirements to compile original Node.js:BUILDING.md
Usage of packaged app
Command line call to packaged app ./app a b
is equivalentto node app.js a b
Snapshot filesystem
During packaging process pkg
collects project files and placesthem into executable. It is called a snapshot. At run time thepackaged application has access to snapshot filesystem where allthat files reside.
Packaged files have /snapshot/
prefix in their paths (orC:\snapshot\
in Windows). If you used pkg /path/app.js
command line,then __filename
value will be likely /snapshot/path/app.js
at run time. __dirname
will be /snapshot/path
as well. Here isthe comparison table of path-related values:
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 |
Hence, in order to make use of a file collected at packagingtime (require
a javascript file or serve an asset) you shouldtake __filename
, __dirname
, process.pkg.defaultEntrypoint
or require.main.filename
as a base for your path calculations.For javascript files you can just require
or require.resolve
because they use current __dirname
by default. For assets usepath.join(__dirname, '../path/to/asset')
. Learn more aboutpath.join
inDetecting assets in source code.
On the other hand, in order to access real file system at run time(pick up a user's external javascript plugin, json configuration oreven get a list of user's directory) you should take process.cwd()
or path.dirname(process.execPath)
.
Detecting assets in source code
When pkg
encounters path.join(__dirname, '../path/to/asset')
,it automatically packages the file specified as an asset. SeeAssets. Pay attention that path.join
must have twoarguments and the last one must be a string literal.
This way you may even avoid creating pkg
config for your project..
使用样例:
pkg package.json -t node7-win-x86 --output zmdog.exe --debug
打包成EXE 后读取配置文件使用:
js文件中需要使用process.cwd
require(path.join(process.cwd(),'cfg.json' ))
需要使用path.join( process.cwd())
如果是只读的文件,需要打包到exe中,就只需要使用path.join(__dirname,'somefile')
资源文件打包 需要定义节点
package.json
file.
"pkg": {
"scripts": "build/**/*.js",
"assets": "views/**/*"
}
即可打包成单一的exe,项目只读文件是快照的方式存放在内存,同时也可访问真实文件。
打包速度还挺快。