アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

npm_package_config と npm_config

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.jsonconfig 欄に解説されている。

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.jsonconfig プロパティに 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 from WordPress

  • mysticatea mysticatea 2016-09-14T23:59:12Z

    ちなみにですが、npm_package_configの方も CLI オプションから指定できます。

    記法は --パッケージ名:変数名=値 です。

    冒頭の{"name": "foo", "config": {"port": "8080"}}の場合は、npm run task --foo:port=8000

  • アカベコ アカベコ 2016-09-15T12:00:56Z

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

Copyright © 2009 - 2023 akabeko.me All Rights Reserved.