npx と yarn
◆ package.json の bin で追加されたコマンドを実行できる
◆ npx はその場でダウンロードして実行もできる
◆ yarn は yarn2 の dlx コマンドでできるようになる
◆ npx はその場でダウンロードして実行もできる
◆ yarn は yarn2 の dlx コマンドでできるようになる
bin
npm パッケージはインストールするときに package.json の bin に設定されたコマンドが使えるようになりますnpm にテスト用を置くのは気がすすまないので Gist にテスト用のパッケージを作りました
package.json はこうなっています
{
"name": "test-command",
"version": "1.0.0",
"bin": {
"test-comm1": "./cli.js",
"test-comm2": "./cli.js"
}
}
これをインストールします
yarn add gist:f403bc36fbdecc9199a3919a022e691f
インストール後の node_modules はこうなります
node_modules/
.bin/
test-comm1
test-comm1.cmd
test-comm2
test-comm2.cmd
test-command/
(略)
.bin
.bin フォルダに bin に設定したスクリプトが入っています同じコマンドにファイルが 2 種類あるのは Windows と Linux 両方に対応するためのもので どっちでも指定したコマンドが実行できるようになっています
.bin フォルダにはパスは通っていないので
node_modules/.bin/test-command1 a b c
のように直接指定することになりますがこれは面倒です
yarn の場合は yarn run を使って .bin の中にあるコマンドを指定するとそれを実行してくれます
yarn run test-comm1 a b c
他の yarn コマンドとかぶらなければ run を省略しても動きます
yarn test-comm1 a b c
yarn じゃなくて npm の場合は npx というコマンドになります
npx test-comm1 a b c
実行例
実際に動かしてみますcli.js は引数を表示するだけのものです
winuser@WIN10 MINGW64 /c/tmp/04
$ yarn run test-comm1
yarn run v1.22.4
warning package.json: No license field
$ C:\tmp\04\node_modules\.bin\test-comm1
cli arguments is ...
[
'C:\\Program Files\\nodejs\\node.exe',
'C:\\tmp\\04\\node_modules\\test-command\\cli.js'
]
Done in 0.18s.
winuser@WIN10 MINGW64 /c/tmp/04
$ yarn test-comm2
yarn run v1.22.4
warning package.json: No license field
$ C:\tmp\04\node_modules\.bin\test-comm2
cli arguments is ...
[
'C:\\Program Files\\nodejs\\node.exe',
'C:\\tmp\\04\\node_modules\\test-command\\cli.js'
]
Done in 0.17s.
npx
npx はインストールしたパッケージ以外にも使えますnode_modules に無いなら一時フォルダにダウンロードしてから実行されます
一応キャッシュが使われてるようなので 同じものを毎回ダウンロードしてるわけではなさそうです
ただ ローカルの PC 内で毎回展開したりの処理はあるのでインストール済みに比べると待ち時間はあります
頻繁に使うものなら package.json に追加してインストールしたほうがいいですが 一回限りでいいようなものでは便利です
winuser@WIN10 MINGW64 /c/tmp/07
$ npx gist:f403bc36fbdecc9199a3919a022e691f x y z
npx: 1個のパッケージを7.777秒でインストールしました。
cli arguments is ...
[
'C:\\Program Files\\nodejs\\node.exe',
'C:\\Users\\winuser\\AppData\\Roaming\\npm-cache\\_npx\\11624\\node_modules\\test-command\\cli.js',
'x',
'y',
'z'
]
npx を使うときは基本コマンドを選択できません
パッケージにコマンドが複数あって選択する場合は -p オプションを使ってパッケージを指定します
winuser@WIN10 MINGW64 /c/tmp/07
$ npx -p gist:f403bc36fbdecc9199a3919a022e691f test-comm2 x y z
npx: 1個のパッケージを8.33秒でインストールしました。
cli arguments is ...
[
'C:\\Program Files\\nodejs\\node.exe',
'C:\\Users\\winuser\\AppData\\Roaming\\npm-cache\\_npx\\5620\\node_modules\\test-command\\cli.js',
'x',
'y',
'z'
]
yarn dlx
npx のダウンロードして実行機能を yarn でも実行したかったのですが 存在しないようですタイプミスとか フォルダ間違って実行した場合は普通はエラーになるだけなのに パッケージをダウンロードして実行することで予想外の動作があっても困りますからね
有名パッケージのありがちなタイプミスの名前で 「rm -rf /」 が実行されるパッケージとかあると怖いですし
とはいえ不便なので調べてみるとこんな issue がありました
https://github.com/yarnpkg/yarn/issues/3937
「yarn dlx」 という別の名前が提案されています
yarn2 のドキュメントを見ると dlx コマンドがありました
https://yarnpkg.com/cli/dlx
yarn2 からは使えるようです
実行したコマンドはわからない
上の方の結果を見ると分かる通り 引数の 0 番目が Node.js ランタイムの場所ですそして 1 番目が JavaScript ファイルで 2 番目以降がコマンドラインで渡した引数です
つまり bin コマンドのどっちを実行したかという情報がありません
Node.js みたいなランタイムを使わない実行可能ファイルだと 実体はひとつで別名のシンボリックリンクを用意して実行されたコマンド名に応じて処理を変えるというのはわりと見る方法です
それをやりたかったのですが Node.js では無理みたいですね
ただ npx の例でよく見る cowsay では cowthink を使ってるのを見た気がします
https://github.com/piuccio/cowsay
package.json は同じものを指定していて
"bin": {
"cowsay": "./cli.js",
"cowthink": "./cli.js"
},
ヘルプメッセージにも cowthink で実行すると変わるようなことが書かれています
If the program is invoked as cowthink then the cow will think its message instead of saying it.
ソースコードを見ましたが コマンドライン引数を正規表現チェックして think で終わるかをチェックしていたので動くようには思えません
一応実行もしてみましたが常に say で think してくれませんでした
実行コマンド名での出し分けは無理そうなので package.json の bin で指定するファイルを変えたほうがよさそうです
[追記]
.bin フォルダ内がシンボリックリンクの場合には動くようです
シンボリックリンクの場合は cli.js へのシンボリックリンクとなります
この場合 最初の引数が Node.js ランタイムなのは変わりませんが その次の JavaScript ファイルがシンボリックリンクファイルの名前になります
これを見ることで実行したコマンドを判断することができます
ただ シンボリックリンクとして配置されるとは限らないので環境依存であることに注意が必要です
.bin フォルダ内がシンボリックリンクの場合には動くようです
シンボリックリンクの場合は cli.js へのシンボリックリンクとなります
この場合 最初の引数が Node.js ランタイムなのは変わりませんが その次の JavaScript ファイルがシンボリックリンクファイルの名前になります
これを見ることで実行したコマンドを判断することができます
ただ シンボリックリンクとして配置されるとは限らないので環境依存であることに注意が必要です