Node.jsでのシェルスクリプト
この書籍のオフライン版(HTML、PDF、EPUB、MOBI)を購入して、無料オンライン版をサポートできます。
(広告、ブロックしないでください。)

15 npmパッケージスクリプトによるクロスプラットフォームタスクの実行



package.jsonには、アーティファクトのコンパイルやテストの実行など、パッケージ関連のタスクを実行する小さなシェルスクリプトであるパッケージスクリプトを定義できるプロパティ"scripts"があります。この章では、それらと、WindowsとUnix(macOS、Linuxなど)の両方で機能するように記述する方法について説明します。

15.1 npmパッケージスクリプト

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>

このオプションについては、ロギングに関するセクションで詳しく説明します。

15.1.1 パッケージスクリプトを実行するための短いnpmコマンド

一部のパッケージスクリプトは、より短いnpmコマンドで実行できます。

コマンド 同等
npm testnpm t npm run test
npm start npm run start
npm stop npm run stop
npm restart npm run restart

15.1.2 パッケージスクリプトの実行に使用されるシェルは?

デフォルトでは、npmはWindowsではcmd.exeを介して、Unixでは/bin/shを介してパッケージスクリプトを実行します。npm構成設定script-shellを介して変更できます。

ただし、そうするのは良い考えではないことがほとんどです。既存の多くのクロスプラットフォームスクリプトはshおよびcmd.exe用に記述されており、動作しなくなります。

15.1.3 パッケージスクリプトが自動的に実行されるのを防ぐ

一部のスクリプト名は、npmが特定のnpmコマンドを実行するたびに実行されるライフサイクルスクリプト用に予約されています。

たとえば、npmは(引数なしで)npm installを実行するたびにスクリプト"postinstall"を実行します。ライフサイクルスクリプトについては後で詳しく説明します。

構成設定ignore-scriptstrueの場合、npmはスクリプトを自動的に実行しません。直接呼び出した場合にのみ実行します。

15.1.4 Unixでのパッケージスクリプトのタブ補完

Unixでは、npmはnpm completionを介してコマンドとパッケージスクリプト名のタブ補完をサポートしています。これをインストールするには、次の行を.profile / .zprofile / .bash_profileなどに追加します。

. <(npm completion)

Unix以外のプラットフォームでタブ補完が必要な場合は、「npmタブ補完PowerShell」などのWeb検索を行ってください。

15.1.5 パッケージスクリプトのリストと整理

名前のない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/
15.1.5.1 区切り記号の追加

パッケージスクリプトが多い場合は、スクリプト名を区切り記号として誤用できます(スクリプト"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の両方で機能することに注意してください。

15.1.5.2 ヘルプ情報の印刷

パッケージスクリプト"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.                                  ║
╚═══════╧══════════════════════════════════════════╝

15.2 パッケージスクリプトの種類

特定の名前がスクリプトに使用されている場合、特定の状況で自動的に実行されます。

その他すべてのスクリプトは、直接実行スクリプトと呼ばれます。

15.2.1 preスクリプトとpostスクリプト

npmがパッケージスクリプトPSを実行するたびに、次のスクリプトが存在する場合は自動的に実行します。

次のスクリプトには、preスクリプトprehelloとpostスクリプトposthelloが含まれています。

"scripts": {
  "hello": "echo hello",
  "prehello": "echo BEFORE",
  "posthello": "echo AFTER"
},

helloを実行した場合に発生する内容は次のとおりです。

% npm -s run hello
BEFORE
hello
AFTER

15.2.2 ライフサイクルスクリプト

npmは、次のようなnpmコマンド中にライフサイクルスクリプトを実行します。

いずれかのライフサイクルスクリプトが失敗した場合、コマンド全体がエラーで即座に停止します。

ライフサイクルスクリプトのユースケースは何ですか?

これらは、最も重要なライフサイクルスクリプトです(すべてのライフサイクルスクリプトの詳細については、npmドキュメントを参照してください)。

次の表は、これらのライフサイクルスクリプトがいつ実行されるかをまとめたものです。

prepublishOnly prepack prepare install
npm publish
npm pack
npm install
グローバルインストール
git、パス経由のインストール

注意点:自動化は常に少しトリッキーです。私は通常、次のルールに従います。

15.3 パッケージスクリプトが実行されるシェル環境

このセクションでは、時々次を使用します。

node -p <expr>

これは expr 内の JavaScript コードを実行し、その結果をターミナルに出力します。たとえば、

% node -p "'hello everyone!'.toUpperCase()" 
HELLO EVERYONE!

15.3.1 現在のディレクトリ

パッケージスクリプトが実行されるとき、現在のディレクトリは常にパッケージディレクトリになります。これは、ルートとなるディレクトリツリー内のどこにいるかに依存しません。package.json に次のスクリプトを追加することで確認できます。

"cwd": "node -p \"process.cwd()\""

Unix で cwd を試してみましょう。

% cd /Users/robin/new-package/src/util 
% npm -s run cwd
/Users/robin/new-package

このように現在のディレクトリを変更すると、パッケージディレクトリを基準としたパスを使用できるため、パッケージスクリプトの作成に役立ちます。

15.3.2 シェルのPATH

モジュール M が、パッケージ P の名前で始まる指定子を持つモジュールからインポートする場合、Node.js は P のディレクトリを見つけるまで node_modules ディレクトリを検索します。

つまり、M はその先祖ディレクトリの node_modules ディレクトリを継承します。

同様の継承は、パッケージをインストールすると node_modules/.bin に保存される bin スクリプトでも発生します。npm run は、一時的にシェルの PATH 変数(Unix では $PATH、Windows では %Path%)にエントリを追加します。

これらの追加を確認するために、次のパッケージスクリプトを使用できます。

"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'
]

15.4 パッケージスクリプトでの環境変数の使用

Make、Grunt、Gulp などのタスクランナーでは、変数は冗長性を減らすのに役立つため、重要です。残念ながら、パッケージスクリプトには独自の変数はありませんが、環境変数シェル変数とも呼ばれます)を使用することで、その欠点を回避できます。

プラットフォーム固有の環境変数を一覧表示するには、次のコマンドを使用できます。

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_ の下には、現在実行中のパッケージスクリプトの名前と定義があります。

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',

15.4.1 環境変数の取得と設定

次の 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"
}

15.4.2 .env ファイルによる環境変数の設定

.env ファイルを介して環境変数を設定できるパッケージもあります。これらのファイルは次の形式です。

# Comment
SECRET_HOST="https://example.com"
SECRET_KEY="123456789" # another comment

package.json とは別のファイルを使用すると、そのデータをバージョン管理から除外できます。

これらは .env ファイルをサポートするパッケージです。

15.5 パッケージスクリプトの引数

パッケージスクリプトを介して呼び出すシェルコマンドに引数がどのように渡されるかを調べましょう。次の 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' ]

15.6 npm のログレベル(どのくらいの出力が生成されるか)

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 種類のアクティビティを指します。

次のサブセクションでは、以下について説明します。

15.6.1 ターミナルに出力されるログレベルと情報

デフォルトでは、パッケージスクリプトはターミナル出力に関して比較的冗長です。たとえば、次の 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
%

15.6.2 npm ログに書き込まれるログレベルと情報

デフォルトでは、ログは 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

15.6.3 ログの構成

npm config list --long は、さまざまな設定のデフォルト値を表示します。これらは、ログ関連の設定のデフォルト値です。

% npm config list --long | grep log
loglevel = "notice"
logs-dir = null
logs-max = 10

logs-dir の値が null の場合、npm は(前述のように)npm キャッシュディレクトリ内の _logs ディレクトリを使用します。

これらの設定を永続的に変更するには、npm config も使用します。たとえば、

コマンドラインオプションを使用して設定を一時的に変更することもできます。たとえば、

npm --loglevel silent run build

設定を変更する他の方法(環境変数の使用など)は、npm ドキュメントで説明されています。

15.6.4 npm install 中に実行されるライフサイクルスクリプトの出力

(引数なしの)npm install 中に実行されるライフサイクルスクリプトの出力は非表示になっています。foreground-scripts を(一時的または永続的に)true に設定することで、それを変更できます。

15.6.5 npm ログ記録の動作に関する考察

15.7 クロスプラットフォームのシェルスクリプト

パッケージスクリプトで最も一般的に使用される 2 つのシェルは次のとおりです。

このセクションでは、両方のシェルで動作する構造について調べます。

15.7.1 パスとクォーティング

ヒント

15.7.2 コマンドの連結

両方のプラットフォームで動作するコマンドを連結する方法は2つあります。

終了コードを無視した連結はプラットフォームによって異なります。

次のやり取りは、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

15.7.3 パッケージスクリプトの終了コード

終了コードはシェル変数を使用してアクセスできます。

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

15.7.4 パイプ処理と入出力のリダイレクト

15.7.5 両方のプラットフォームで動作するコマンド

次のコマンドは両方のプラットフォームに存在しますが、オプションに関しては異なります。

15.7.6 binスクリプトとパッケージ内部モジュールの実行

次のpackage.jsonは、依存関係にあるbinスクリプトを呼び出す3つの方法を示しています。

{
  "scripts": {
    "hi1": "./node_modules/.bin/cowsay Hello",
    "hi2": "cowsay Hello",
    "hi3": "npx cowsay Hello"
  },
  "dependencies": {
    "cowsay": "^1.5.0"
  }
}

説明

Unixでは、ハッシュバンがあり、実行可能であれば、パッケージローカルのスクリプトを直接呼び出すことができます。ただし、Windowsでは機能しないため、node経由で呼び出す方が良いでしょう。

"build": "node ./build.mjs"

15.7.7 node --evalnode --print

パッケージスクリプトの機能が複雑になりすぎた場合は、Node.jsモジュールを介して実装するのが良いアイデアです。これにより、クロスプラットフォームのコードを簡単に作成できます。

ただし、nodeコマンドを使用して、小さなJavaScriptスニペットを実行することもできます。これは、クロスプラットフォームで小さなタスクを実行する場合に便利です。関連するオプションは次のとおりです。

次のコマンドは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}`

観察

15.8 一般的な操作のためのヘルパーパッケージ

15.8.1 コマンドラインからのパッケージスクリプトの実行

npm-quick-runは、パッケージスクリプトを実行するために略語を使用できるbinスクリプトnrを提供します。たとえば、

15.8.2 複数のスクリプトの同時または逐次的な実行

シェルスクリプトの同時実行

次の2つのパッケージは、その機能と関連機能に対するクロスプラットフォームオプションを提供します。

15.8.3 ファイルシステムの操作

パッケージ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コマンドに加えて、catchmodechofindgrepheadlnlsmvpwdsedsorttailtouchuniqなどもエミュレートします。

15.8.4 ファイルまたはディレクトリをゴミ箱に入れる

パッケージtrash-cliは、macOS(10.12+)、Linux、およびWindows(8+)で動作します。ファイルとディレクトリをゴミ箱に入れ、パスとグロブパターンをサポートします。以下は、その使用例です。

trash tmp-file.txt
trash tmp-dir
trash "*.jpg"

15.8.5 ファイルのツリーのコピー

パッケージ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

15.8.6 ファイルの監視

パッケージonchangeは、ファイルを監視し、ファイルが変更されるたびにシェルコマンドを実行します。たとえば、

onchange 'app/**/*.js' 'test/**/*.js' -- npm test

一般的な代替手段の1つ(他の多くの中で)

15.8.7 その他の機能

15.8.8 HTTPサーバー

開発中には、HTTPサーバーがあると便利なことがよくあります。以下のパッケージ(他の多くの中で)が役立ちます。

15.9 パッケージスクリプトの機能の拡張

15.9.1 per-env: $NODE_ENVに応じてスクリプトを切り替える

binスクリプトper-envを使用すると、パッケージスクリプトSCRIPTを実行し、環境変数NODE_ENVの値に応じて、(例: )SCRIPT:developmentSCRIPT: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"
    }
  }
}

15.9.2 オペレーティングシステム固有のスクリプトの定義

binスクリプトcross-osは、現在のオペレーティングシステムに応じてスクリプトを切り替えます。

{
  "scripts": {
    "user": "cross-os user"
  },
  "cross-os": {
    "user": {
      "darwin": "echo $USER",
      "win32": "echo %USERNAME%",
      "linux": "echo $USER"
    }
  },
  ···
}

サポートされているプロパティ値は、darwinfreebsdlinuxsunoswin32です。

15.10 この章のソース