npm_package_config と npm_config

2016年9月14日 2 開発 , , , ,

npm-run-allSupport npm config params という issue から npm_config の存在を知った。以前、npm-scripts 内で変数を展開したくなって cross-conf-env を開発した時に npm_package_config は調べたが、この npm_config も外部から npm-scripts にパラメータを渡す仕組みのようである。

これらの性質や用途について、簡単にまとめてみる。

npm_package_config

package.json の config 欄に解説されている。

A “config” object can be used to set configuration parameters used in package scripts that persist across upgrades. For instance, if a package had the following:

{ "name" : "foo"
, "config" : { "port" : "8080" } }

and then had a “start” command that then referenced the npm_package_config_port environment variable, then the user could override that by doing npm config set foo:port 8001.

package.json の config プロパティに key/value を定義することで npm-scripts 内へ npm_package_config_key と展開する機能。

公式資料では言及されていないのだが、npm-scripts は Shell になるため、macOS などの bash 系は $npm_package_config_key、Windows のコマンドプロンプトや PowerShell では %npm_package_config_key% のように定義する。

Node プログラム上からは process.env.npm_package_config_key として参照可能。

私の作成した cross-conf-env では、これらと修飾文字なしの npm_package_config をサポートしており、混在させても展開するところが特徴。つまり Shell を問わず好きな書式で記述できるようにしてある。

この機能を利用すると npm-scripts 内のパラメータを直値から変数にできる。npm-scripts 間で重複する値があるとか、頻繁に更新される値があるなら変数化して config プロパティ側の編集だけで済ませられるようにしておくと便利だ。

実例は akabekobeko/examples-electron を参照のこと。このリポジトリは複数の Electron プロジェクトを管理しているが、これらの npm-scripts は共通化され config プロパティでアプリ名などを分岐している。

npm_config

config に解説されている。この資料は npm_package_config に対しても言及あり。

npm_package_config と異なり、こちらは npm run される時の引数として渡されたパラメータを展開する。例えば

{
  "scripts": {
    "task": "echo npm_config_foo npm_config_bar"
  }
}

のように npm-scripts を定義して、以下のようにパラメータを渡す。

$ npm run task --foo=Foo --bar=Bar

Foo Bar

npm run されるスクリプトのオプションに --key=value を指定すると、スクリプト内の npm_config_key に展開される。Node プログラム上からは process.env.npm_config_key として参照可能。

package.json 外からパラメータを渡すとか、npm-scripts を多段実行する時に npm_package_config 代わりにするとかで役立つのかもしれない。本記事のきっかけとなった npm-run-all は npm-scripts を同期・非同期で多段実行するための npm なので、これに対応する必要があったのだろう。

npm_config が展開される側は Shell なので前述のとおり にプラットフォームごとの修飾文字が必要。cross-conf-env は v1.0.6 で対応した。

まとめ

私はプロジェクトに関する情報をなるべく package.json へ静的に定義したいので、npm_package_config のほうが好みだ。しかしこちらは config の定義が必要なうえ記述も長い。よって npm-scripts の多段実行は必要になるけれど、より短い npm_config も便利な場面があるかもしれない。

package.json で確定不能な設定については npm_config に頼らざるを得ない。npm_scripts を実行するのは主に開発者なので、このようなケースはあまり考えられないのだが、npm から取得できない環境情報なんかを渡すときによいのだろうか。

ほぼ共通の設定で一部だけ異なる npm-scripts があるときに便利かもしれない。そういえば Browserify の require オプションでモジュールを外部公開するを書いた後に業務で

  • 共通処理を定義した main.js
  • サブフォルダ単位で個別のデータを定義した data.js
  • HTML 上で main.js と組み合わせる data.js を変更することで、ページ内容が切り替えられる

という感じの Web サイトをビルドする機会があって、サブフォルダが増えるたびにその名前だけ変更した npm-scripts を追加する運用を考えていた。

しかしこれは面倒なので npm_config によりフォルダ名を部分展開するほうがスマートな気がする。複数同時に生成するとしても、npm-scripts の多段実行を前提とすれば package.json で完結できる。

記事のまとめに軽く考察でも、と雑に書いていたら業務の問題がひとつ解決してしまった。


COMMENTS

  • mysticatea
    2016年9月15日 8:59 AM 返信

    ちなみにですが、`npm_package_config`の方も CLI オプションから指定できます。
    記法は `–パッケージ名:変数名=値` です。
    冒頭の`{“name”: “foo”, “config”: {“port”: “8080”}}`の場合は、`npm run task –foo:port=8000`。

    • 2016年9月15日 9:00 PM 返信

      情報提供ありがとうございます。npm_package_config の場合はハイフンがひとつなのですね。

REPLY

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です