CLOVER🍀

That was when it all began.

Node.jsのコマンドラインオプションをNODE_OPTIONS環境変数で指定する

これは、なにをしたくて書いたもの?

Node.jsのコマンドラインオプションを環境変数で指定できないのかな?と思って調べてみたのですが、NODE_OPTIONS環境変数
これに該当しそうなので、試してみます。

NODE_OPTIONS環境変数

NODE_OPTIONS環境変数は、こちらに記載があります。

Command-line API / Environment variables / NODE_OPTIONS=options...

NODE_OPTIONS環境変数には、スペース区切りでオプションを指定するようです。

A space-separated list of command-line options.

指定したオプションはコマンドラインオプションの前に解釈されるので、同時に使うとコマンドラインオプションで指定した方が優先される
(オーバーライドする)挙動になるようですね。

options... are interpreted before command-line options, so command-line options will override or compound after anything in options....

それぞれ、例が書かれています。

オプションの値にスペースが含まれる場合は、引用符で囲います。

$ NODE_OPTIONS='--require "./my path/file.js"'

NODE_OPTIONS環境変数コマンドラインオプションで同じオプションを指定した場合で、かつフラグのように1度だけ指定する
オプションは、コマンドラインオプションの方が優先(オーバーライド)されます。

# The inspector will be available on port 5555
$ NODE_OPTIONS='--inspect=localhost:4444' node --inspect=localhost:5555

複数回指定できるオプションの場合は、両方を合わせた結果になるようですね。

$ NODE_OPTIONS='--require "./a.js"' node --require "./b.js"
# is equivalent to:
node --require "./a.js" --require "./b.js"

また、指定可能なコマンドラインオプションおよびV8オプションは規定されているようです。

指定可能なコマンドラインオプションはこちら。

  • --conditions, -C
  • --diagnostic-dir
  • --disable-proto
  • --dns-result-order
  • --enable-fips
  • --enable-source-maps
  • --experimental-abortcontroller
  • --experimental-fetch
  • --experimental-global-webcrypto
  • --experimental-import-meta-resolve
  • --experimental-json-modules
  • --experimental-loader
  • --experimental-modules
  • --experimental-network-imports
  • --experimental-policy
  • --experimental-specifier-resolution
  • --experimental-top-level-await
  • --experimental-vm-modules
  • --experimental-wasi-unstable-preview1
  • --experimental-wasm-modules
  • --force-context-aware
  • --force-fips
  • --frozen-intrinsics
  • --heapsnapshot-near-heap-limit
  • --heapsnapshot-signal
  • --http-parser
  • --icu-data-dir
  • --input-type
  • --insecure-http-parser
  • --inspect-brk
  • --inspect-port</code>, <code>--debug-port
  • --inspect-publish-uid
  • --inspect
  • --max-http-header-size
  • --napi-modules
  • --no-addons
  • --no-deprecation
  • --no-experimental-repl-await
  • --no-force-async-hooks-checks
  • --no-global-search-paths
  • --no-warnings
  • --node-memory-debug
  • --openssl-config
  • --pending-deprecation
  • --policy-integrity
  • --preserve-symlinks-main
  • --preserve-symlinks
  • --prof-process
  • --redirect-warnings
  • --report-compact
  • --report-dir</code>, <code>--report-directory
  • --report-filename
  • --report-on-fatalerror
  • --report-on-signal
  • --report-signal
  • --report-uncaught-exception
  • --require</code>, <code>-r
  • --secure-heap-min
  • --secure-heap
  • --throw-deprecation
  • --title
  • --tls-cipher-list
  • --tls-keylog
  • --tls-max-v1.2
  • --tls-max-v1.3
  • --tls-min-v1.0
  • --tls-min-v1.1
  • --tls-min-v1.2
  • --tls-min-v1.3
  • --trace-atomics-wait
  • --trace-deprecation
  • --trace-event-categories
  • --trace-event-file-pattern
  • --trace-events-enabled
  • --trace-exit
  • --trace-sigint
  • --trace-sync-io
  • --trace-tls
  • --trace-uncaught
  • --trace-warnings
  • --track-heap-objects
  • --unhandled-rejections
  • --use-bundled-ca
  • --use-largepages
  • --use-openssl-ca
  • --v8-pool-size
  • --zero-fill-buffers

指定可能なV8オプションは、以下になります。

  • --abort-on-uncaught-exception
  • --disallow-code-generation-from-strings
  • --huge-max-old-generation-size
  • --interpreted-frames-native-stack
  • --jitless
  • --max-old-space-size
  • --perf-basic-prof-only-functions
  • --perf-basic-prof
  • --perf-prof-unwinding-info
  • --perf-prof
  • --stack-trace-limit

また、以下のオプションはLinux環境のみで有効です。

  • --perf-basic-prof-only-functions
  • --perf-basic-prof
  • --perf-prof-unwinding-info
  • --perf-prof

確認はこれくらいにして、自分でも試してみましょう。

環境

今回の環境は、こちらです。

$ node --version
v16.16.0

確認してみる

--max-old-space-sizeを使って確認してみましょう。

Command-line API / Useful V8 options / --max-old-space-size=SIZE (in megabytes)

サンプルプログラム。

app.js

const v8 = require('v8');

console.log(`heap total available size = ${Math.floor(v8.getHeapStatistics().total_available_size / 1024 / 1024)} MB`);

まずは、ふつうに実行してみます。

$ node app.js
heap total available size = 4141 MB

NODE_OPTIONS環境変数を使って、--max-old-space-sizeを指定してみます。

$ NODE_OPTIONS='--max-old-space-size=1536' node app.js
heap total available size = 1581 MB

反映されたようです。

コマンドラインオプションと両方指定してみましょう。

$ NODE_OPTIONS='--max-old-space-size=1536' node --max-old-space-size=2048 app.js
heap total available size = 2093 MB

コマンドラインオプションで指定した方が優先されましたね。

最後に、複数指定してみましょう。--max-old-space-sizeに加えて、--inspect-brkも指定してみます。

$ NODE_OPTIONS='--max-old-space-size=1536 --inspect-brk' node app.js 
Debugger listening on ws://127.0.0.1:9229/6643fd31-bf72-4a94-8144-982fcf779991
For help, see: https://nodejs.org/en/docs/inspector

起動すると--inspect-brkが効いてすぐに待ちになるので、chrome://inspectにアクセスしてDevToolsで対象のプロセスを開きます。

アタッチされて停止しているプログラムを進めていくと、--max-old-space-sizeも効いていることが確認できます。

heap total available size = 1580 MB

こんな感じでしょうか。覚えておこうと思います。