.envファイルを介した環境変数の設定npm install中に実行されるライフサイクルスクリプトの出力node --evalとnode --printper-env:$NODE_ENVに応じてスクリプトを切り替えるpackage.jsonには、アーティファクトのコンパイルやテストの実行など、パッケージ関連のタスクを実行する小さなシェルスクリプトであるパッケージスクリプトを定義できるプロパティ"scripts"があります。この章では、それらと、WindowsとUnix(macOS、Linuxなど)の両方で機能するように記述する方法について説明します。
npmパッケージスクリプトは、package.jsonのプロパティ"scripts"を介して定義されます。
{
···
"scripts": {
"tsc": "tsc",
"tscwatch": "tsc --watch",
"tscclean": "shx rm -rf ./dist/*"
},
···
}"scripts"の値は、各プロパティがパッケージスクリプトを定義するオブジェクトです。
次のように入力すると
npm run <script-name>
npmは、script-nameという名前のスクリプトをシェルで実行します。たとえば、次のように使用できます。
npm run tscwatch
シェルで次のコマンドを実行します。
tsc --watch
この章では、npmオプション-sを時々使用します。これは--silentの省略形であり、npm runに出力を少なくするように指示します。
npm -s run <script-name>
このオプションについては、ロギングに関するセクションで詳しく説明します。
一部のパッケージスクリプトは、より短いnpmコマンドで実行できます。
| コマンド | 同等 |
|---|---|
npm test、npm t |
npm run test |
npm start |
npm run start |
npm stop |
npm run stop |
npm restart |
npm run restart |
npm start:パッケージスクリプト"start"がない場合、npmはnode server.jsを実行します。npm restart:パッケージスクリプト"restart"がない場合、npmは"prerestart"、"stop"、"start"、"postrestart"を実行します。デフォルトでは、npmはWindowsではcmd.exeを介して、Unixでは/bin/shを介してパッケージスクリプトを実行します。npm構成設定script-shellを介して変更できます。
ただし、そうするのは良い考えではないことがほとんどです。既存の多くのクロスプラットフォームスクリプトはshおよびcmd.exe用に記述されており、動作しなくなります。
一部のスクリプト名は、npmが特定のnpmコマンドを実行するたびに実行されるライフサイクルスクリプト用に予約されています。
たとえば、npmは(引数なしで)npm installを実行するたびにスクリプト"postinstall"を実行します。ライフサイクルスクリプトについては後で詳しく説明します。
構成設定ignore-scriptsがtrueの場合、npmはスクリプトを自動的に実行しません。直接呼び出した場合にのみ実行します。
Unixでは、npmはnpm completionを介してコマンドとパッケージスクリプト名のタブ補完をサポートしています。これをインストールするには、次の行を.profile / .zprofile / .bash_profileなどに追加します。
. <(npm completion)Unix以外のプラットフォームでタブ補完が必要な場合は、「npmタブ補完PowerShell」などのWeb検索を行ってください。
名前のないnpm runは、使用可能なスクリプトを一覧表示します。次のスクリプトが存在する場合
"scripts": {
"tsc": "tsc",
"tscwatch": "tsc --watch",
"serve": "serve ./site/"
}次のようにリストされます。
% npm run
Scripts available via `npm run-script`:
tsc
tsc
tscwatch
tsc --watch
serve
serve ./site/
パッケージスクリプトが多い場合は、スクリプト名を区切り記号として誤用できます(スクリプト"help"については、次のサブセクションで説明します)。
"scripts": {
"help": "scripts-help -w 40",
"\n========== Building ==========": "",
"tsc": "tsc",
"tscwatch": "tsc --watch",
"\n========== Serving ==========": "",
"serve": "serve ./site/"
},これで、スクリプトは次のようにリストされます。
% npm run
Scripts available via `npm run-script`:
help
scripts-help -w 40
========== Building ==========
tsc
tsc
tscwatch
tsc --watch
========== Serving ==========
serve
serve ./site/
改行(\n)を先頭に追加するトリックは、UnixとWindowsの両方で機能することに注意してください。
パッケージスクリプト"help"は、パッケージ@rauschma/scripts-helpのbinスクリプトscripts-helpを介してヘルプ情報を出力します。package.jsonプロパティ"scripts-help"を介して説明を提供します("tscwatch"の値は、1行に収まるように省略されています)。
"scripts-help": {
"tsc": "Compile the TypeScript to JavaScript.",
"tscwatch": "Watch the TypeScript source code [...]",
"serve": "Serve the generated website via a local server."
}これがヘルプ情報の外観です
% npm -s run help
Package “demo”
╔══════╤══════════════════════════╗
║ help │ scripts-help -w 40 ║
╚══════╧══════════════════════════╝
Building
╔══════════╤══════════════════════════════════════════╗
║ tsc │ Compile the TypeScript to JavaScript. ║
╟──────────┼──────────────────────────────────────────╢
║ tscwatch │ Watch the TypeScript source code and ║
║ │ compile it incrementally when and if ║
║ │ there are changes. ║
╚══════════╧══════════════════════════════════════════╝
Serving
╔═══════╤══════════════════════════════════════════╗
║ serve │ Serve the generated website via a local ║
║ │ server. ║
╚═══════╧══════════════════════════════════════════╝
特定の名前がスクリプトに使用されている場合、特定の状況で自動的に実行されます。
npm installなどのアクションを実行するときに実行されます。その他すべてのスクリプトは、直接実行スクリプトと呼ばれます。
npmがパッケージスクリプトPSを実行するたびに、次のスクリプトが存在する場合は自動的に実行します。
prePS(preスクリプト)postPS(postスクリプト)次のスクリプトには、preスクリプトprehelloとpostスクリプトposthelloが含まれています。
"scripts": {
"hello": "echo hello",
"prehello": "echo BEFORE",
"posthello": "echo AFTER"
},helloを実行した場合に発生する内容は次のとおりです。
% npm -s run hello
BEFORE
hello
AFTER
npmは、次のようなnpmコマンド中にライフサイクルスクリプトを実行します。
npm publish(npmレジストリにパッケージをアップロードします)npm pack(レジストリパッケージ、パッケージディレクトリなどのアーカイブを作成します)npm install(npmレジストリ以外のソースからダウンロードされたパッケージの依存関係をインストールするために引数なしで使用されます)いずれかのライフサイクルスクリプトが失敗した場合、コマンド全体がエラーで即座に停止します。
ライフサイクルスクリプトのユースケースは何ですか?
TypeScriptのコンパイル:パッケージにTypeScriptコードが含まれている場合、通常、使用する前にJavaScriptコードにコンパイルします。後者のコードはバージョン管理にチェックインされないことがよくありますが、パッケージをJavaScriptから使用できるように、npmレジストリにアップロードする必要があります。ライフサイクルスクリプトを使用すると、npm publishがパッケージをアップロードする前にTypeScriptコードをコンパイルできます。これにより、npmレジストリでは、JavaScriptコードが常にTypeScriptコードと同期していることが保証されます。また、コンパイル(したがって公開)がエラーが発生した場合に停止するため、TypeScriptコードに静的な型エラーがないことも保証されます。
テストの実行:ライフサイクルスクリプトを使用して、パッケージを公開する前にテストを実行することもできます。テストが失敗した場合、パッケージは公開されません。
これらは、最も重要なライフサイクルスクリプトです(すべてのライフサイクルスクリプトの詳細については、npmドキュメントを参照してください)。
"prepare":
.tgzファイル)が作成される前に実行されます。npm publish中npm pack中npm install が引数なしで使用された場合、またはパッケージがグローバルにインストールされた場合に実行されます。"prepack" は、パッケージアーカイブ(.tgz ファイル)が作成される前に実行されます。npm publish中npm pack中"prepublishOnly" は npm publish 中のみ実行されます。"install" は、npm install が引数なしで使用された場合、またはパッケージがグローバルにインストールされた場合に実行されます。"preinstall" および/またはポストスクリプト "postinstall" を作成することもできます。これらの名前から、npmがいつ実行するかがより明確になります。次の表は、これらのライフサイクルスクリプトがいつ実行されるかをまとめたものです。
prepublishOnly |
prepack |
prepare |
install |
|
|---|---|---|---|---|
npm publish |
✔ |
✔ |
✔ |
|
npm pack |
✔ |
✔ |
||
npm install |
✔ |
✔ |
||
| グローバルインストール | ✔ |
✔ |
||
| git、パス経由のインストール | ✔ |
注意点:自動化は常に少しトリッキーです。私は通常、次のルールに従います。
prepublishOnlyを使用)。postinstallを使用)。このセクションでは、時々次を使用します。
node -p <expr>
これは expr 内の JavaScript コードを実行し、その結果をターミナルに出力します。たとえば、
% node -p "'hello everyone!'.toUpperCase()"
HELLO EVERYONE!
パッケージスクリプトが実行されるとき、現在のディレクトリは常にパッケージディレクトリになります。これは、ルートとなるディレクトリツリー内のどこにいるかに依存しません。package.json に次のスクリプトを追加することで確認できます。
"cwd": "node -p \"process.cwd()\""Unix で cwd を試してみましょう。
% cd /Users/robin/new-package/src/util
% npm -s run cwd
/Users/robin/new-package
このように現在のディレクトリを変更すると、パッケージディレクトリを基準としたパスを使用できるため、パッケージスクリプトの作成に役立ちます。
モジュール M が、パッケージ P の名前で始まる指定子を持つモジュールからインポートする場合、Node.js は P のディレクトリを見つけるまで node_modules ディレクトリを検索します。
M の親ディレクトリの node_modules (存在する場合)M の親ディレクトリの親ディレクトリの node_modules (存在する場合)つまり、M はその先祖ディレクトリの node_modules ディレクトリを継承します。
同様の継承は、パッケージをインストールすると node_modules/.bin に保存される bin スクリプトでも発生します。npm run は、一時的にシェルの PATH 変数(Unix では $PATH、Windows では %Path%)にエントリを追加します。
node_modules/.binnode_modules/.binこれらの追加を確認するために、次のパッケージスクリプトを使用できます。
"bin-dirs": "node -p \"JS\""JS は、この JavaScript コードを含む 1 行を表します。
(process.env.PATH ?? process.env.Path)
.split(path.delimiter)
.filter(p => p.includes('.bin'))Unix で bin-dirs を実行すると、次の出力が得られます。
% npm -s run bin-dirs
[
'/Users/robin/new-package/node_modules/.bin',
'/Users/robin/node_modules/.bin',
'/Users/node_modules/.bin',
'/node_modules/.bin'
]
Windows では、次のようになります。
>npm -s run bin-dirs
[
'C:\\Users\\charlie\\new-package\\node_modules\\.bin',
'C:\\Users\\charlie\\node_modules\\.bin',
'C:\\Users\\node_modules\\.bin',
'C:\\node_modules\\.bin'
]
Make、Grunt、Gulp などのタスクランナーでは、変数は冗長性を減らすのに役立つため、重要です。残念ながら、パッケージスクリプトには独自の変数はありませんが、環境変数(シェル変数とも呼ばれます)を使用することで、その欠点を回避できます。
プラットフォーム固有の環境変数を一覧表示するには、次のコマンドを使用できます。
envSETnode -p process.envmacOS では、結果は次のようになります。
TERM_PROGRAM=Apple_Terminal
SHELL=/bin/zsh
TMPDIR=/var/folders/ph/sz0384m11vxf5byk12fzjms40000gn/T/
USER=robin
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
PWD=/Users/robin/new-package
HOME=/Users/robin
LOGNAME=robin
···
Windows コマンドシェルでは、結果は次のようになります。
Path=C:\Windows;C:\Users\charlie\AppData\Roaming\npm;···
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROMPT=$P$G
TEMP=C:\Users\charlie\AppData\Local\Temp
TMP=C:\Users\charlie\AppData\Local\Temp
USERNAME=charlie
USERPROFILE=C:\Users\charlie
···
さらに、npm はパッケージスクリプトを実行する前に、一時的に追加の環境変数を追加します。最終的な結果を確認するには、次のコマンドを使用できます。
npm run env
このコマンドは、組み込みのパッケージスクリプトを呼び出します。この package.json で試してみましょう。
{
"name": "@my-scope/new-package",
"version": "1.0.0",
"bin": {
"hello": "./hello.mjs"
},
"config": {
"stringProp": "yes",
"arrayProp": ["a", "b", "c"],
"objectProp": {
"one": 1,
"two": 2
}
}
}npm の一時変数の名前はすべて npm_ で始まります。それらをアルファベット順にのみ出力しましょう。
npm run env | grep npm_ | sort
npm_ 変数は階層構造を持っています。npm_lifecycle_ の下には、現在実行中のパッケージスクリプトの名前と定義があります。
npm_lifecycle_event: 'env',
npm_lifecycle_script: 'env',Windows では、npm_lifecycle_script はこの場合 SET となります。
プレフィックス npm_config_ の下には、npm の構成設定の一部(npm ドキュメントに記載)を確認できます。これらはいくつかの例です。
npm_config_cache: '/Users/robin/.npm',
npm_config_global_prefix: '/usr/local',
npm_config_globalconfig: '/usr/local/etc/npmrc',
npm_config_local_prefix: '/Users/robin/new-package',
npm_config_prefix: '/usr/local'
npm_config_user_agent: 'npm/8.15.0 node/v18.7.0 darwin arm64 workspaces/false',
npm_config_userconfig: '/Users/robin/.npmrc',
プレフィックス npm_package_ を使用すると、package.json の内容にアクセスできます。トップレベルは次のようになります。
npm_package_json: '/Users/robin/new-package/package.json',
npm_package_name: '@my-scope/new-package',
npm_package_version: '1.0.0',
npm_package_bin_ の下には、package.json プロパティ "bin" のプロパティがあります。
npm_package_bin_hello: 'hello.mjs',
npm_package_config_ エントリを使用すると、"config" のプロパティにアクセスできます。
npm_package_config_arrayProp: 'a\n\nb\n\nc',
npm_package_config_objectProp_one: '1',
npm_package_config_objectProp_two: '2',
npm_package_config_stringProp: 'yes',
つまり、"config" を使用して、パッケージスクリプトで使用できる変数を設定できます。次のサブセクションでは、それをさらに詳しく調べます。
オブジェクトは「ネストされた」エントリ(2行目と3行目)に変換され、配列(1行目)と数値(2行目と3行目)は文字列に変換されたことに注意してください。
これらは残りの npm_ 環境変数です。
npm_command: 'run-script',
npm_execpath: '/usr/local/lib/node_modules/npm/bin/npm-cli.js',
npm_node_execpath: '/usr/local/bin/node',
次の package.json は、パッケージスクリプトで "config" を介して定義された変数にアクセスする方法を示しています。
{
"scripts": {
"hi:unix": "echo $npm_package_config_hi",
"hi:windows": "echo %npm_package_config_hi%"
},
"config": {
"hi": "HELLO"
}
}残念ながら、パッケージスクリプトから環境変数にアクセスするための組み込みのクロスプラットフォームな方法はありません。
ただし、役に立つ bin スクリプトを持つパッケージがあります。
パッケージ env-var を使用すると、環境変数を取得できます。
"scripts": {
"hi": "env-var echo {{npm_package_config_hi}}"
}パッケージ cross-env を使用すると、環境変数を設定できます。
"scripts": {
"build": "cross-env FIRST=one SECOND=two node ./build.mjs"
}.env ファイルによる環境変数の設定.env ファイルを介して環境変数を設定できるパッケージもあります。これらのファイルは次の形式です。
# Comment
SECRET_HOST="https://example.com"
SECRET_KEY="123456789" # another comment
package.json とは別のファイルを使用すると、そのデータをバージョン管理から除外できます。
これらは .env ファイルをサポートするパッケージです。
パッケージ dotenv は、JavaScript モジュールに対してそれらをサポートします。プリロードできます。
node -r dotenv/config app.mjs
そして、インポートできます。
import dotenv from 'dotenv';
dotenv.config();
console.log(process.env);パッケージ node-env-run を使用すると、シェルコマンドを介して .env ファイルを使用できます。
# Loads `.env` and runs an arbitrary shell script.
# If there are CLI options, we need to use `--`.
nodenv --exec node -- -p process.env.SECRET
# Loads `.env` and uses `node` to run `script.mjs`.
nodenv script.mjsパッケージ env-cmd は、前のパッケージの代替です。
# Loads `.env` and runs an arbitrary shell script
env-cmd node -p process.env.SECRET
このパッケージには、変数のセットの切り替え、より多くのファイル形式など、より多くの機能があります。
パッケージスクリプトを介して呼び出すシェルコマンドに引数がどのように渡されるかを調べましょう。次の package.json を使用します。
{
···
"scripts": {
"args": "log-args"
},
"dependencies": {
"log-args": "^1.0.0"
}
}bin スクリプト log-args は次のようになります。
for (const [key,value] of Object.entries(process.env)) {
if (key.startsWith('npm_config_arg')) {
console.log(`${key}=${JSON.stringify(value)}`);
}
}
console.log(process.argv.slice(2));位置引数は期待どおりに機能します。
% npm -s run args three positional arguments
[ 'three', 'positional', 'arguments' ]
npm run はオプションを消費し、それらの環境変数を作成します。それらは process.argv に追加されません。
% npm -s run args --arg1='first arg' --arg2='second arg'
npm_config_arg2="second arg"
npm_config_arg1="first arg"
[]
オプションを process.argv に表示したい場合は、オプションターミネーター -- を使用する必要があります。そのターミネーターは通常、パッケージスクリプトの名前の後ろに挿入されます。
% npm -s run args -- --arg1='first arg' --arg2='second arg'
[ '--arg1=first arg', '--arg2=second arg' ]
ただし、その名前の前に挿入することもできます。
% npm -s run -- args --arg1='first arg' --arg2='second arg'
[ '--arg1=first arg', '--arg2=second arg' ]
npm は次のログレベルをサポートしています。
| ログレベル | npm オプション |
エイリアス |
|---|---|---|
| silent | --loglevel silent |
-s --silent |
| error | --loglevel error |
|
| warn | --loglevel warn |
-q --quiet |
| notice | --loglevel notice |
|
| http | --loglevel http |
|
| timing | --loglevel timing |
|
| info | --loglevel info |
-d |
| verbose | --loglevel verbose |
-dd --verbose |
| silly | --loglevel silly |
-ddd |
ログ記録とは、次の 2 種類のアクティビティを指します。
次のサブセクションでは、以下について説明します。
ログレベルがこれらのアクティビティにどのように影響するか。原則として、silent は最も少なくログを記録し、silly は最も多くログを記録します。
ログを構成する方法。前の表は、コマンドラインオプションを使用してログレベルを一時的に変更する方法を示していますが、さらに多くの設定があります。それらは一時的にまたは永続的に変更できます。
デフォルトでは、パッケージスクリプトはターミナル出力に関して比較的冗長です。たとえば、次の package.json ファイルを見てみましょう。
{
"name": "@my-scope/new-package",
"version": "1.0.0",
"scripts": {
"hello": "echo Hello",
"err": "more does-not-exist.txt"
},
···
}ログレベルが silent より高く、パッケージスクリプトがエラーなしで終了した場合に発生します。
% npm run hello
> @my-scope/new-package@1.0.0 hello
> echo Hello
Hello
ログレベルが silent より高く、パッケージスクリプトが失敗した場合に発生します。
% npm run err
> @my-scope/new-package@1.0.0 err
> more does-not-exist.txt
does-not-exist.txt: No such file or directory
ログレベル silent を使用すると、出力がすっきりします。
% npm -s run hello
Hello
% npm -s run err
does-not-exist.txt: No such file or directory
一部のエラーは -s によって抑制されます。
% npm -s run abc
%
それらを表示するには、少なくともログレベル error が必要です。
% npm --loglevel error run abc
npm ERR! Missing script: "abc"
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR! npm run
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/robin/.npm/_logs/2072-08-30T14_59_40_474Z-debug-0.log
残念ながら、ログレベル silent は、(引数なしの) npm run の出力も抑制します。
% npm -s run
%
デフォルトでは、ログは npm キャッシュディレクトリに書き込まれます。そのパスは npm config を使用して取得できます。
% npm config get cache
/Users/robin/.npm
ログディレクトリの内容は次のようになります。
% ls -1 /Users/robin/.npm/_logs
2072-08-28T11_44_38_499Z-debug-0.log
2072-08-28T11_45_45_703Z-debug-0.log
2072-08-28T11_52_04_345Z-debug-0.log
ログの各行は、行インデックスとログレベルで始まります。これは、ログレベル notice で書き込まれたログの例です。興味深いことに、notice よりも「詳細」なログレベル(silly など)でさえ、ログに表示されます。
0 verbose cli /usr/local/bin/node /usr/local/bin/npm
1 info using npm@8.15.0
···
33 silly logfile done cleaning log files
34 timing command:run Completed in 9ms
···
npm run がエラーで返される場合、対応するログはこのように終わります。
34 timing command:run Completed in 7ms
35 verbose exit 1
36 timing npm Completed in 28ms
37 verbose code 1
エラーがない場合、対応するログはこのように終わります。
34 timing command:run Completed in 7ms
35 verbose exit 0
36 timing npm Completed in 26ms
37 info ok
npm config list --long は、さまざまな設定のデフォルト値を表示します。これらは、ログ関連の設定のデフォルト値です。
% npm config list --long | grep log
loglevel = "notice"
logs-dir = null
logs-max = 10
logs-dir の値が null の場合、npm は(前述のように)npm キャッシュディレクトリ内の _logs ディレクトリを使用します。
logs-dir を使用すると、npm がログを書き込むディレクトリを任意に指定できます。logs-max を使用すると、npm が古いファイルを削除する前にログディレクトリに書き込まれるファイルの数を構成できます。logs-max を 0 に設定すると、ログは書き込まれません。loglevel を使用すると、npm のログレベルを構成できます。これらの設定を永続的に変更するには、npm config も使用します。たとえば、
現在のログレベルを取得する
npm config get loglevel現在のログレベルを永続的に設定する
npm config set loglevel silentログレベルを組み込みのデフォルトに永続的にリセットする
npm config delete loglevelコマンドラインオプションを使用して設定を一時的に変更することもできます。たとえば、
npm --loglevel silent run build
設定を変更する他の方法(環境変数の使用など)は、npm ドキュメントで説明されています。
npm install 中に実行されるライフサイクルスクリプトの出力(引数なしの)npm install 中に実行されるライフサイクルスクリプトの出力は非表示になっています。foreground-scripts を(一時的または永続的に)true に設定することで、それを変更できます。
npm run を使用するときに追加の出力をオフにするのは、ログレベル silent のみです。パッケージスクリプトで最も一般的に使用される 2 つのシェルは次のとおりです。
shcmd.exeこのセクションでは、両方のシェルで動作する構造について調べます。
ヒント
セグメントがスラッシュで区切られた相対パスを使用してください。Windowsでは、通常はバックスラッシュを使用しますが、スラッシュも区切り文字として受け入れます。
引数をダブルクォートで囲んでください。shはシングルクォートをサポートしていますが、Windowsコマンドシェルはサポートしていません。残念ながら、パッケージスクリプトの定義で使用する際には、ダブルクォートをエスケープする必要があります。
"dir": "mkdir \"\my dir""両方のプラットフォームで動作するコマンドを連結する方法は2つあります。
&&の後のコマンドは、前のコマンドが成功した場合(終了コードが0の場合)にのみ実行されます。||の後のコマンドは、前のコマンドが失敗した場合(終了コードが0以外の場合)にのみ実行されます。終了コードを無視した連結はプラットフォームによって異なります。
;&次のやり取りは、Unixでの&&と||の動作を示しています(Windowsではlsの代わりにdirを使用します)。
% ls unknown && echo "SUCCESS" || echo "FAILURE"
ls: unknown: No such file or directory
FAILURE
% ls package.json && echo "SUCCESS" || echo "FAILURE"
package.json
SUCCESS
終了コードはシェル変数を使用してアクセスできます。
$?%errorlevel%npm runは、最後に実行されたシェルスクリプトと同じ終了コードを返します。
{
···
"scripts": {
"hello": "echo Hello",
"err": "more does-not-exist.txt"
}
}次のやり取りはUnixで発生します。
% npm -s run hello ; echo $?
Hello
0
% npm -s run err ; echo $?
does-not-exist.txt: No such file or directory
1
|cmd > stdout-saved-to-file.txtcmd < stdin-from-file.txt次のコマンドは両方のプラットフォームに存在しますが、オプションに関しては異なります。
cdecho。Windowsでの注意点:ダブルクォートは無視されず、出力されます。exitmkdirmorermdirsort次のpackage.jsonは、依存関係にあるbinスクリプトを呼び出す3つの方法を示しています。
{
"scripts": {
"hi1": "./node_modules/.bin/cowsay Hello",
"hi2": "cowsay Hello",
"hi3": "npx cowsay Hello"
},
"dependencies": {
"cowsay": "^1.5.0"
}
}説明
hi1: 依存関係にあるbinスクリプトは、ディレクトリnode_modules/.binにインストールされます。
hi2: すでに説明したように、npmはパッケージスクリプトを実行する間、シェルPATHにnode_modules/.binを追加します。つまり、ローカルのbinスクリプトをグローバルにインストールされているかのように使用できます。
hi3: npxがスクリプトを実行するとき、シェルPATHにnode_modules/.binも追加します。
Unixでは、ハッシュバンがあり、実行可能であれば、パッケージローカルのスクリプトを直接呼び出すことができます。ただし、Windowsでは機能しないため、node経由で呼び出す方が良いでしょう。
"build": "node ./build.mjs"node --evalとnode --printパッケージスクリプトの機能が複雑になりすぎた場合は、Node.jsモジュールを介して実装するのが良いアイデアです。これにより、クロスプラットフォームのコードを簡単に作成できます。
ただし、nodeコマンドを使用して、小さなJavaScriptスニペットを実行することもできます。これは、クロスプラットフォームで小さなタスクを実行する場合に便利です。関連するオプションは次のとおりです。
node --eval <expr>は、JavaScript式exprを評価します。node -enode --print <expr>は、JavaScript式exprを評価し、結果をターミナルに出力します。node -p次のコマンドはUnixとWindowsの両方で動作します(コメントはUnix固有のものです)。
# Print a string to the terminal (cross-platform echo)
node -p "'How are you?'"
# Print the value of an environment variable
# (Alas, we can’t change variables via `process.env`)
node -p process.env.USER # only Unix
node -p process.env.USERNAME # only Windows
node -p "process.env.USER ?? process.env.USERNAME"
# Print all environment variables
node -p process.env
# Print the current working directory
node -p "process.cwd()"
# Print the path of the current home directory
node -p "os.homedir()"
# Print the path of the current temporary directory
node -p "os.tmpdir()"
# Print the contents of a text file
node -p "fs.readFileSync('package.json', 'utf-8')"
# Write a string to a file
node -e "fs.writeFileSync('file.txt', 'Text content', 'utf-8')"
プラットフォーム固有の行末記号が必要な場合は、os.EOLを使用できます。たとえば、前のコマンドの'Text content'を次のように置き換えることができます。
`line 1${os.EOL}line2${os.EOL}`観察
osやfsをインポートする必要はありません。fsは、より多くのファイルシステム操作をサポートしています。これらは§8「Node.jsでのファイルシステムの操作」で説明されています。npm-quick-runは、パッケージスクリプトを実行するために略語を使用できるbinスクリプトnrを提供します。たとえば、
nr m -wは、"npm run mocha -- -w"を実行します("mocha"が「m」で始まる最初のパッケージスクリプトである場合)。nr c:oは、パッケージスクリプト"cypress:open"を実行します。シェルスクリプトの同時実行
&start次の2つのパッケージは、その機能と関連機能に対するクロスプラットフォームオプションを提供します。
concurrentlyは、複数のシェルコマンドを同時に実行します。たとえば、
concurrently "npm run clean" "npm run build"npm-run-allは、いくつかの種類の機能を提供します。たとえば、
パッケージスクリプトを順番に呼び出すためのより便利な方法。次の2つのコマンドは同等です。
npm-run-all clean lint build
npm run clean && npm run lint && npm run buildパッケージスクリプトの同時実行
npm-run-all --parallel lint buildワイルドカードを使用して複数のスクリプトを実行します。たとえば、watch:*はwatch:html、watch:jsなどのwatch:で始まるすべてのパッケージスクリプトを表します。
npm-run-all "watch:*"
npm-run-all --parallel "watch:*"パッケージshxを使用すると、「Unix構文」を使用してさまざまなファイルシステム操作を実行できます。実行するすべての操作は、UnixとWindowsで動作します。
ディレクトリの作成
"create-asset-dir": "shx mkdir ./assets"ディレクトリの削除
"remove-asset-dir": "shx rm -rf ./assets"ディレクトリのクリア(ワイルドカード記号*に関する安全のためにダブルクォートを使用)
"tscclean": "shx rm -rf \"./dist/*\""ファイルのコピー
"copy-index": "shx cp ./html/index.html ./out/index.html"ファイルの削除
"remove-index": "shx rm ./out/index.html"shxはJavaScriptライブラリShellJSに基づいており、そのリポジトリにはサポートされているすべてのコマンドがリストされています。すでに見てきたUnixコマンドに加えて、cat、chmod、echo、find、grep、head、ln、ls、mv、pwd、sed、sort、tail、touch、uniqなどもエミュレートします。
パッケージtrash-cliは、macOS(10.12+)、Linux、およびWindows(8+)で動作します。ファイルとディレクトリをゴミ箱に入れ、パスとグロブパターンをサポートします。以下は、その使用例です。
trash tmp-file.txt
trash tmp-dir
trash "*.jpg"
パッケージcopyfilesを使用すると、ファイルのツリーをコピーできます。
以下はcopyfilesの使用例です。TypeScriptでは、CSSや画像などのコード以外の資産をインポートできます。TypeScriptコンパイラはコードを「dist」(出力)ディレクトリにコンパイルしますが、コード以外の資産は無視します。このクロスプラットフォームのシェルコマンドは、それらをdistディレクトリにコピーします。
copyfiles --up 1 "./ts/**/*.{css,png,svg,gif}" ./distTypeScriptコンパイル
my-pkg/ts/client/picker.ts -> my-pkg/dist/client/picker.js
copy-assetsコピー
my-pkg/ts/client/picker.css -> my-pkg/dist/client/picker.css
my-pkg/ts/client/icon.svg -> my-pkg/dist/client/icon.svg
パッケージonchangeは、ファイルを監視し、ファイルが変更されるたびにシェルコマンドを実行します。たとえば、
onchange 'app/**/*.js' 'test/**/*.js' -- npm test
一般的な代替手段の1つ(他の多くの中で)
開発中には、HTTPサーバーがあると便利なことがよくあります。以下のパッケージ(他の多くの中で)が役立ちます。
per-env: $NODE_ENVに応じてスクリプトを切り替えるbinスクリプトper-envを使用すると、パッケージスクリプトSCRIPTを実行し、環境変数NODE_ENVの値に応じて、(例: )SCRIPT:development、SCRIPT:staging、およびSCRIPT:productionを自動的に切り替えます。
{
"scripts": {
// If NODE_ENV is missing, the default is "development"
"build": "per-env",
"build:development": "webpack -d --watch",
"build:staging": "webpack -p",
"build:production": "webpack -p"
},
// Processes spawned by `per-env` inherit environment-specific
// variables, if defined.
"per-env": {
"production": {
"DOCKER_USER": "my",
"DOCKER_REPO": "project"
}
}
}binスクリプトcross-osは、現在のオペレーティングシステムに応じてスクリプトを切り替えます。
{
"scripts": {
"user": "cross-os user"
},
"cross-os": {
"user": {
"darwin": "echo $USER",
"win32": "echo %USERNAME%",
"linux": "echo $USER"
}
},
···
}サポートされているプロパティ値は、darwin、freebsd、linux、sunos、win32です。
Ryan ZimmermanとMichael Kühnelによる「Awesome npm scripts」
Dominik Kundelによる「Three Things You Didn’t Know You Could Do with npm Scripts」
Michael Kühnelによる「Helpers and tips for npm run scripts」