.env
ファイルを介した環境変数の設定npm install
中に実行されるライフサイクルスクリプトの出力node --eval
とnode --print
per-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/.bin
node_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 などのタスクランナーでは、変数は冗長性を減らすのに役立つため、重要です。残念ながら、パッケージスクリプトには独自の変数はありませんが、環境変数(シェル変数とも呼ばれます)を使用することで、その欠点を回避できます。
プラットフォーム固有の環境変数を一覧表示するには、次のコマンドを使用できます。
env
SET
node -p process.env
macOS では、結果は次のようになります。
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_
の下には、現在実行中のパッケージスクリプトの名前と定義があります。
: 'env',
npm_lifecycle_event: 'env', npm_lifecycle_script
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';
.config();
dotenvconsole.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 つのシェルは次のとおりです。
sh
cmd.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.txt
cmd < stdin-from-file.txt
次のコマンドは両方のプラットフォームに存在しますが、オプションに関しては異なります。
cd
echo
。Windowsでの注意点:ダブルクォートは無視されず、出力されます。exit
mkdir
more
rmdir
sort
次の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 -e
node --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}" ./dist
TypeScriptコンパイル
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」