Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
This repository was archived by the owner on Jan 13, 2024. It is now read-only.
/pkgPublic archive

Package your Node.js project into an executable

License

NotificationsYou must be signed in to change notification settings

vercel/pkg

Repository files navigation

Important

pkg has been deprecated with5.8.1 as the last release. There are a number of successful forked versions ofpkg already with various feature additions. Further, we’re excited about Node.js 21’s support forsingle executable applications. Thank you for the support and contributions over the years. The repository will remain open and archived.

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 vianpm 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, runpkg --help without arguments to see list of options:

pkg [options] <input>  Options:    -h, --help           output usage information    -v, --version        output pkg version    -t, --targets        comma-separated list of targets (see examples)    -c, --config         package.json or any json file with top-level config    --options            bake v8 options into executable to run with them on    -o, --output         output file name or template for several files    --out-path           path to save output one or more executables    -d, --debug          show more information during packaging process [off]    -b, --build          don't download prebuilt base binaries, build them    --public             speed up and disclose the sources of top-level project    --public-packages    force specified packages to be considered public    --no-bytecode        skip bytecode generation and include source files as plain js    --no-native-build    skip native addons build    --no-signature       skip signature of the final executable on macos    --no-dict            comma-separated list of packages names to ignore dictionaries. Use --no-dict * to disable all dictionaries    -C, --compress       [default=None] compression algorithm = Brotli or GZip  Examples:  – Makes executables for Linux, macOS and Windows    $ pkg index.js  – Takes package.json from cwd and follows 'bin' entry    $ pkg .  – Makes executable for particular target machine    $ pkg -t node16-win-arm64 index.js  – Makes executables for target machines of your choice    $ pkg -t node16-linux,node18-linux,node16-win index.js  – Bakes '--expose-gc' and '--max-heap-size=34' into executable    $ pkg --options "expose-gc,max-heap-size=34" index.js  – Consider packageA and packageB to be public    $ pkg --public-packages "packageA,packageB" index.js  – Consider all packages to be public    $ pkg --public-packages "*" index.js  – Bakes '--expose-gc' into executable    $ pkg --options expose-gc index.js  – reduce size of the data packed inside the executable with GZip    $ pkg --compress GZip index.js

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 topackage.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--targetsoption. A canonical target consists of 3 elements, separated bydashes, for examplenode18-macos-x64 ornode14-linux-arm64:

  • nodeRange (node8), node10, node12, node14, node16 or latest
  • platform alpine, linux, linuxstatic, win, macos, (freebsd)
  • arch x64, arm64, (armv6, armv7)

(element) is unsupported, but you may try to compile yourself.

You may omit any element (and specify justnode14 for example).The omitted elements will be taken from current platform orsystem-wide Node.js installation (its version and arch).There is also an aliashost, 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.

If you want to generate executable for different architectures,note that by defaultpkg has to run the executable of thetarget arch to generate bytecodes:

  • Linux: configure binfmt withQEMU.
  • macOS: possible to buildx64 onarm64 withRosetta 2 but not opposite.
  • Windows: possible to buildx64 onarm64 withx64 emulation but not opposite.
  • or, disable bytecode generation with--no-bytecode --public-packages "*" --public.

macos-arm64 is experimental. Be careful about themandatory code signing requirement.The final executable has to be signed (ad-hoc signature is sufficient) withcodesignutility of macOS (orldid utility on Linux). Otherwise, the executable will be killedby kernel and the end-user has no way to permit it to run at all.pkg tries to ad-hocsign the final executable. If necessary, you can replace this signature with your owntrusted Apple Developer ID.

To be able to generate executables for all supported architectures and platforms, runpkg on a Linux host with binfmt (QEMU emulation) configured andldid installed.

Config

During packaging processpkg parses your sources, detectscalls torequire, traverses the dependencies of your projectand includes them into executable. In most cases youdon't need to specify anything manually.

However your code may haverequire(variable) calls (so called non-literalargument torequire) or use non-javascript files (forexample views, css, images etc).

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

Such cases are not handled bypkg. So you must specify thefiles - scripts and assets - manually inpkg property ofyourpackage.json file.

"pkg": {"scripts":"build/**/*.js","assets":"views/**/*","targets": ["node14-linux-arm64" ],"outputPath":"dist"  }

The above example will include everything inassets/ andevery .js file inbuild/, build only fornode14-linux-arm64,and place the executable insidedist/.

You may also specify arrays of globs:

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

Just be sure to callpkg package.json orpkg . to makeuse ofpackage.json configuration.

Scripts

scripts is aglobor list of globs. Files specified asscripts will be compiledusingv8::ScriptCompiler and placed into executable withoutsources. They must conform to the JS standards of those Node.js versionsyou target (seeTargets), i.e. be already transpiled.

Assets

assets is aglobor list of globs. Files specified asassets will be packagedinto executable as raw content without modifications. Javascriptfiles may also be specified asassets. Their sources willnot be stripped as it improves execution performance of thefiles 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 typenode --help ornode --v8-options.

You can "bake" these runtime options into packaged application. The app will always run with the optionsturned on. Just remove-- from option name.

You can specify multiple options by joining them in a single string, comma (,) separated:

pkg app.js --options expose-gcpkg app.js --options max_old_space_size=4096pkg app.js --options max-old-space-size=1024,tls-min-v1.0,expose-gc

Output

You may specify--output if you create only one executableor--out-path to place executables for multiple targets.

Debug

Pass--debug topkg 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.

Bytecode (reproducibility)

By default, your source code is precompiled to v8 bytecode before being writtento the output file. To disable this feature, pass--no-bytecode topkg.

Why would you want to do this?

If you need a reproducible buildprocess where your executable hashes (e.g. md5, sha1, sha256, etc.) are thesame value between builds. Because compiling bytecode is not deterministic(seehere orhere) itresults in executables with differing hashed values. Disabling bytecodecompilation allows a given input to always have the same output.

Why would you NOT want to do this?

While compiling to bytecode does not make your source code 100% secure, it doesadd a small layer of security/privacy/obscurity to your source code. Turningoff bytecode compilation causes the raw source code to be written directly tothe executable file. If you're on *nix machine and would like an example, runpkg with the--no-bytecode flag, and use the GNU strings tool on theoutput. You then should be able to grep your source code.

Other considerations

Specifying--no-bytecode will fail if there are any packages in your project that aren't explicitly markedas public by thelicense in theirpackage.json.By default,pkg will check the license of each package and make sure that stuff that isn't meant for the public willonly be included as bytecode.

If you do require building pkg binaries for other architectures and/or depend on a package with a brokenlicense in itspackage.json, you can override this behaviour by either explicitly whitelisting packages to be publicusing--public-packages "packageA,packageB" or setting all packages to public using--public-packages "*"

Build

pkg has so called "base binaries" - they are actually samenode executables but with some patches applied. They areused as a base for every executablepkg creates.pkgdownloads precompiled base binaries before packaging yourapplication. If you prefer to compile base binaries fromsource instead of downloading them, you may pass--buildoption topkg. First ensure your computer meets therequirements to compile original Node.js:BUILDING.md

Seepkg-fetch for more info.

Compression

Pass--compress Brotli or--compress GZip topkg to compress further the content of the files store in the exectable.

This option can reduce the size of the embedded file system by up to 60%.

The startup time of the application might be reduced slightly.

-C can be used as a shortcut for--compress.

Environment

VarDescription
PKG_CACHE_PATHUsed to specify a custom path for node binaries cache folder. Default is~/.pkg-cache
PKG_IGNORE_TAGAllows to ignore additional folder created onPKG_CACHE_PATH matching pkg-fetch version
MAKE_JOB_COUNTAllow configuring number of processes used for compiling

Examples

# 1 - Using exportexport PKG_CACHE_PATH=/my/cachepkg app.js# 2 - Passing it before the scriptPKG_CACHE_PATH=/my/cache pkg app.js

Usage of packaged app

Command line call to packaged app./app a b is equivalenttonode app.js a b

Snapshot filesystem

During packaging processpkg 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 usedpkg /path/app.js command line,then__filename value will be likely/snapshot/path/app.jsat run time.__dirname will be/snapshot/path as well. Here isthe comparison table of path-related values:

valuewithnodepackagedcomments
__filename/project/app.js/snapshot/project/app.js
__dirname/project/snapshot/project
process.cwd()/project/deploysuppose the app is called ...
process.execPath/usr/bin/nodejs/deploy/app-x64app-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.entrypointundefined/snapshot/project/app.js
process.pkg.defaultEntrypointundefined/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.defaultEntrypointorrequire.main.filename as a base for your path calculations.For javascript files you can justrequire orrequire.resolvebecause 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 takeprocess.cwd()orpath.dirname(process.execPath).

Detecting assets in source code

Whenpkg encounterspath.join(__dirname, '../path/to/asset'),it automatically packages the file specified as an asset. SeeAssets. Pay attention thatpath.join must have twoarguments and the last one must be a string literal.

This way you may even avoid creatingpkg config for your project.

Native addons

Native addons (.node files) use is supported. Whenpkg encountersa.node file in arequire call, it will package this like an asset.In some cases (like with thebindings package), the module path is generateddynamicaly andpkg won't be able to detect it. In this case, you shouldadd the.node file directly in theassets field inpackage.json.

The way Node.js requires native addon is different from a classic JSfile. It needs to have a file on disk to load it, butpkg only generatesone file. To circumvent this,pkg will create a temporary file on thedisk. These files will stay on the disk after the process has exitedand will be used again on the next process launch.

When a package, that contains a native module, is being installed,the native module is compiled against current system-wide Node.jsversion. Then, when you compile your project withpkg, pay attentionto--target option. You should specify the same Node.js versionas your system-wide Node.js to make compiled executable compatiblewith.node files.

Note that fully static Node binaries are not capable of loading nativebindings, so you may not use Node bindings withlinuxstatic.

API

const { exec } = require('pkg')

exec(args) takes an array of command line arguments and returnsa promise. For example:

awaitexec(['app.js','--target','host','--output','app.exe']);// do something with app.exe, run, test, upload, deploy, etc

Troubleshooting

Error: ENOENT: no such file or directory, uv_chdir

This error can be caused by deleting the directory the application isrun from. Or, generally, deletingprocess.cwd() directory when theapplication is running.

Error: ERR_INSPECTOR_NOT_AVAILABLE

This error can be caused by usingNODE_OPTIONS variable to force torunnode with the debug mode enabled. Debugging options are disallowed, aspkg executables are usually used for production environments.If you do need to use inspector, you canbuild a debuggable Node.js yourself.

Error: require(...).internalModuleStat is not a function

This error can be caused by usingNODE_OPTIONS variable with somebootstrap ornode options causing conflicts withpkg. SomeIDEs, such asVS Code, may add this env variable automatically.

You could check onUnix systems (Linux/macOS) inbash:

$ printenv| grep NODE

Advanced

exploring virtual file system embedded in debug mode

When you are using the--debug flag when building your executable,pkg add the ability to display the content of the virtual file systemand the symlink table on the console, when the application starts,providing that the environement variable DEBUG_PKG is set.This feature can be useful to inspect if symlinks are correctly handled,and check that all the required files for your application are properlyincorporated to the final executable.

$ pkg --debug app.js -o output$ DEBUG_PKG=1 output

or

C:\> pkg --debug app.js -o output.exeC:\> set DEBUG_PKG=1C:\> output.exe

Note: make sure not to use --debug flag in production.


[8]ページ先頭

©2009-2025 Movatter.jp