2019-10-04

pkgでNode.jsスクリプトを実行バイナリにする

Rubyスクリプトをcross-platformなstandaloneバイナリにしようとして諦めた - あーありがち(2019-10-03)

で Ruby を諦めたので、次は Node.js.

zeit/pkgですごく簡単にできる

zeit/pkg: Package your Node.js project into an executable

試したのは 4.4.0

基本的な使い方は

pkg [-t target] [-o output] <source>

で、必要な stub を自動でダウンロードして依存モジュールも含めて -o で指定した名前の実行バイナリを生成してくれる。

ネットワークが弱い場合はこのダウンロードでイライラするけど、そこが済めば1実にあっけなく終わる。本当にあっという間。

ただし、通常ではできあがったバイナリはすごくでかい。どれだけ簡単なコードでも 30MB 以上になってしまう。もしかしたら V8 の option でサイズの削減はできるかもしれないけど、そこはまだ試していない。

でもcross-compileはできない

README には cross-compile できると書かれているんだけど、これは間違いだった。macOS 上で Windows ターゲットのコンパイルを試してみて、確かにコンパイル自体は動作はするんだけど、実際にできあがったバイナリを実行することはできなかった。Windows 上で Windows ターゲットのバイナリを作ったら普通に実行できたので、CI のプラットフォームを Windows にして pkg を実行する形でないとダメっぽい。

続きは GitHub Actionsでpkgを使ったNode.js実行バイナリをWindowsを含めてmatrixビルドする - あーありがち(2019-10-05)

localのファイルのrequireはそのままでは相対パスを解決できない

バイナリはできるけど実行すると以下のように怒られる。

Error: Cannot find module 'xxx
Require stack:
- /snapshot/src/index.js
1) If you want to compile the package/file into executable, please pay attention to compilation warnings and specify a literal in 'require' call. 2) If you don't want to compile the package/file into executable and want to 'require' it from filesystem (likely plugin), specify an absolute path in 'require' call using process.cwd() or process.execPath.
   at Function.Module._resolveFilename (internal/modules/cjs/loader.js:608:15)
   at Function.Module._resolveFilename (pkg/prelude/bootstrap.js:1287:46)
   at Function.Module._load (internal/modules/cjs/loader.js:524:27)
   at Module.require (internal/modules/cjs/loader.js:664:19)
   at Module.require (pkg/prelude/bootstrap.js:1166:31)
   at require (internal/modules/cjs/helpers.js:16:16)
   at Object.<anonymous> (/snapshot/src/index.js:0:0)
   at Module._compile (pkg/prelude/bootstrap.js:1261:22)
   at Object.Module._extensions..js (internal/modules/cjs/loader.js:768:10)
   at Module.load (internal/modules/cjs/loader.js:626:32)

解決策としては process.cwd() とか process.execPath ではなく、

https://github.com/zeit/pkg#config

を参考に、package.json に

"pkg": {
  "scripts": "src/**/*.js"
}

みたいなやつを足しておく必要あり。

  1. 環境変数を指定しておくとダウンロードした stub をキャッシュしてくれる 

About

例によって個人のなんちゃらです