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

13 npmパッケージのインストールとbinスクリプトの実行



package.jsonのプロパティ"bin"を使用すると、npmパッケージが提供するシェルスクリプトを指定できます(詳細については、§14「クロスプラットフォームのシェルスクリプトの作成」を参照してください)。このようなパッケージをインストールすると、Node.jsは、コマンドラインからこれらのシェルスクリプト(いわゆるbinスクリプト)にアクセスできるようにします。この章では、binスクリプトを含むパッケージをインストールする2つの方法を探ります。

これらのすべてが何を意味するのか、インストール後にbinスクリプトを実行する方法を探ります。

13.1 npmレジストリパッケージのグローバルインストール

パッケージcowsayには、次のpackage.jsonプロパティがあります。

"bin": {
  "cowsay": "./cli.js",
  "cowthink": "./cli.js"
},

このパッケージをグローバルにインストールするには、npm install -gを使用します。

npm install -g cowsay

注意:Unixでは、sudoを使用する必要がある場合があります(これについてはすぐに学習します)。

sudo npm install -g cowsay

その後、コマンドラインでcowsaycowthinkコマンドを使用できます。

binスクリプトのみがグローバルに利用可能であることに注意してください。Node.jsがnode_modulesディレクトリでベアモジュール指定子を検索する場合、パッケージは無視されます。

13.1.1 グローバルにインストールされているパッケージの確認 npm ls -g

グローバルにインストールされているパッケージとその場所を確認できます。

% npm ls -g
/usr/local/lib
├── corepack@0.12.1
├── cowsay@1.5.0
└── npm@8.15.0

Windowsでは、インストールパスは%AppData%\npmです。例:

>echo %AppData%\npm
C:\Users\jane\AppData\Roaming\npm

13.1.2 パッケージがグローバルにインストールされる場所 npm root -g

macOSでの結果

% npm root -g
/usr/local/lib/node_modules

Windowsでの結果

>npm root -g
C:\Users\jane\AppData\Roaming\npm\node_modules

13.1.3 シェルスクリプトがグローバルにインストールされる場所 npm bin -g

npm bin -gは、npmがシェルスクリプトをグローバルにインストールする場所を教えてくれます。また、そのディレクトリがシェルPATHで使用可能であることを保証します。

macOSでの結果

% npm bin -g
/usr/local/bin

% which cowsay
/usr/local/bin/cowsay

Windowsコマンドシェルでの結果

>npm bin -g
C:\Users\jane\AppData\Roaming\npm

>where cowsay
C:\Users\jane\AppData\Roaming\npm\cowsay
C:\Users\jane\AppData\Roaming\npm\cowsay.cmd

ファイル名拡張子のない実行可能ファイルcowsayは、Cygwin、MinGW、MSYSなどのUnixベースのWindows環境用です。

Windows PowerShellは、gcm cowsayに対してこのパスを返します。

C:\Users\jane\AppData\Roaming\npm\cowsay.ps1

13.1.4 パッケージがグローバルにインストールされる場所? npmインストールプレフィックス

npmのインストールプレフィックスは、パッケージとbinスクリプトがグローバルにインストールされる場所を決定します。

これはmacOSでのインストールプレフィックスです。

% npm config get prefix
/usr/local

したがって

これはWindowsでのインストールプレフィックスです。

>npm config get prefix
C:\Users\jane\AppData\Roaming\npm

したがって

13.1.5 パッケージがグローバルにインストールされる場所の変更

このセクションでは、パッケージがグローバルにインストールされる場所を変更する2つの方法を検討します。

13.1.5.1 npmインストールプレフィックスの変更

パッケージがグローバルにインストールされる場所を変更する1つの方法は、npmインストールプレフィックスを変更することです。

Unix

mkdir ~/npm-global
npm config set prefix '~/npm-global'

Windowsコマンドシェル

mkdir "%UserProfile%\npm-global"
npm config set prefix "%UserProfile%\npm-global"

Windows PowerShell

mkdir "$env:UserProfile\npm-global"
npm config set prefix "$env:UserProfile\npm-global"

構成データは、ホームディレクトリの.npmrcファイルに保存されます。

今後、グローバルインストールは、指定したディレクトリに追加されます。

その後、グローバルにインストールしたbinスクリプトがシェルで見つかるように、npm bin -gディレクトリをシェルのPATHに追加する必要があります。

npmプレフィックスを変更するデメリット:npm自体をアップグレードするように指示すると、npmも新しい場所にインストールされるようになります。

13.1.5.2 Node.jsバージョンマネージャーの使用

Node.jsバージョンマネージャーを使用すると、複数のバージョンのNode.jsを同時にインストールして、切り替えることができます。一般的なものには以下が含まれます。

13.2 npmレジストリパッケージのローカルインストール

cowsayのようなnpmレジストリパッケージをローカル(パッケージ内)にインストールするには、次の手順を実行します。

cd my-package/
npm install cowsay

これにより、次のデータがpackage.jsonに追加されます。

"dependencies": {
  "cowsay": "^1.5.0",
  ···
}

さらに、パッケージは次のディレクトリにダウンロードされます。

my-package/node_modules/cowsay/

Unixでは、npmはbinスクリプト用に次のシンボリックリンクを追加します。

my-package/node_modules/.bin/cowsay -> ../cowsay/cli.js
my-package/node_modules/.bin/cowthink -> ../cowsay/cli.js

Windowsでは、npmはこれらのファイルをmy-package\node_modules\.bin\に追加します。

cowsay
cowsay.cmd
cowsay.ps1
cowthink
cowthink.cmd
cowthink.ps1

拡張子のないファイルは、Cygwin、MinGW、MSYSなどのUnixベースのWindows環境用のスクリプトです。

npm binは、ローカルにインストールされたbinスクリプトがある場所を教えてくれます。たとえば、

% npm bin
/Users/john/my-package/node_modules/.bin

注意:ローカルでは、パッケージは常にpackage.jsonファイルの隣のnode_modulesディレクトリにインストールされます。後者が現在のディレクトリに存在しない場合、npmは先祖ディレクトリでそれを検索し、そこにパッケージをインストールします。npmがパッケージをローカルにインストールする場所を確認するには、npm rootコマンドを使用できます。たとえば(Unix)

% cd $HOME
% npm root
/Users/john/node_modules

ジョンのホームディレクトリにはpackage.jsonはありませんが、npmは先祖ディレクトリに何もインストールできないため、npm rootはこのディレクトリを表示します。現在の場所にパッケージをローカルにインストールすると、package.jsonが作成され、インストールが通常どおりに進行します。

13.2.1 ローカルにインストールされたbinスクリプトの実行

(このサブセクションのすべてのコマンドは、ディレクトリmy-package内で実行されます。)

13.2.1.1 binスクリプトの直接実行

シェルから次のようにcowsayを実行できます。

./node_modules/.bin/cowsay Hello

Unixでは、ヘルパーを設定できます。

alias npm-exec='PATH=$(npm bin):$PATH'

次に、次のコマンドが機能します。

npm-exec cowsay Hello
13.2.1.2 パッケージスクリプト経由でのbinスクリプトの実行

package.jsonにパッケージスクリプトを追加することもできます。

{
  ···
  "scripts": {
    "cowsay": "cowsay"
  },
  ···
}

次に、シェルでこのコマンドを実行できます。

npm run cowsay Hello

これは、npmが一時的に次のエントリをUnixの$PATHに追加するためです。

/Users/john/my-package/node_modules/.bin
/Users/john/node_modules/.bin
/Users/node_modules/.bin
/node_modules/.bin

Windowsでは、同様のエントリが%Path%または$env:Pathに追加されます。

C:\Users\jane\my-package\node_modules\.bin
C:\Users\jane\node_modules\.bin
C:\Users\node_modules\.bin
C:\node_modules\.bin

次のコマンドは、パッケージスクリプトの実行中に存在する環境変数とその値を一覧表示します。

npm run env
13.2.1.3 npx経由でのbinスクリプトの実行

パッケージ内で、npxを使用してbinスクリプトにアクセスできます。

npx cowsay Hello
npx cowthink Hello

npxの詳細については後述します。

13.3 未公開パッケージのインストール

まだ公開していない、または公開しないパッケージがあり、それをインストールしたい場合があります。

/tmp/unpublished-package/ディレクトリに保存されている、名前が@my-scope/unpublished-packageの未公開パッケージがあると仮定しましょう。次のようにして、グローバルで利用可能にすることができます。

cd /tmp/unpublished-package/
npm link

これを行うと

リンクされたパッケージが参照される方法により、変更はすぐに有効になります。変更時に再度リンクする必要はありません。

グローバルインストールが機能したかどうかを確認するには、npm ls -gを使用して、グローバルにインストールされたすべてのパッケージを一覧表示できます。

未公開のパッケージをグローバルにインストールした後(前のサブセクションを参照)、パッケージ(公開または未公開のいずれでも可能)の1つにローカルにインストールするオプションがあります。

cd /tmp/other-package/
npm link @my-scope/unpublished-package

これにより、次のリンクが作成されます。

/tmp/other-package/node_modules/@my-scope/unpublished-package
-> ../../../unpublished-package

デフォルトでは、未公開パッケージはpackage.jsonの依存関係として追加されません。その背後にある理由は、npm linkがレジストリパッケージの未公開バージョンを一時的に操作するために使用されることが多く、依存関係に表示されるべきではないということです。

ローカルリンクの解除

cd /tmp/other-package/
npm uninstall @my-scope/unpublished-package

グローバルリンクの解除

cd /tmp/unpublished-package/
npm uninstall -g

13.3.4 ローカルパス経由での未公開パッケージのインストール

未公開パッケージをローカルにインストールする別の方法は、npm installを使用し、パッケージ名ではなくローカルパスを介して参照することです。

cd /tmp/other-package/
npm install ../unpublished-package

これには2つの効果があります。

まず、次のシンボリックリンクが作成されます。

/tmp/other-package/node_modules/@my-scope/unpublished-package
-> ../../../unpublished-package

次に、依存関係がpackage.jsonに追加されます。

"dependencies": {
  "@my-scope/unpublished-package": "file:../unpublished-package",
  ···
}

この未公開パッケージのインストール方法は、グローバルでも機能します。

cd /tmp/unpublished-package/
npm install -g .

13.3.5 未公開パッケージをインストールするその他の方法

13.4 npx:npmパッケージ内のbinスクリプトをインストールせずに実行する

npxは、npmにバンドルされているbinスクリプトを実行するためのシェルコマンドです。

最も一般的な使い方は次のとおりです。

npx <package-name> arg1 arg2 ...

このコマンドは、package-nameという名前のパッケージをnpxキャッシュにインストールし、パッケージと同じ名前のbinスクリプトを実行します。例えば、

npx cowsay Hello

つまり、最初にインストールしなくてもbinスクリプトを実行できます。npxは、binスクリプトの単発の呼び出しに最も役立ちます。たとえば、多くのフレームワークは新しいプロジェクトをセットアップするためのbinスクリプトを提供しており、これらはしばしばnpxを介して実行されます。

npxがパッケージを初めて使用した後、そのパッケージはキャッシュで使用できるようになり、後続の呼び出しははるかに高速になります。ただし、パッケージがキャッシュにどれくらいの期間残るかはわかりません。したがって、npxはbinスクリプトをグローバルまたはローカルにインストールする代替手段にはなりません。

パッケージに、パッケージ名とは異なる名前のbinスクリプトが付属している場合は、次のようにアクセスできます。

npx --package=<package-name> <bin-script> arg1 arg2 ...

例えば

npx --package=cowsay cowthink Hello

13.4.1 npxキャッシュ

npxのキャッシュはどこにありますか?

Unixでは、次のコマンドで確認できます。

npx --package=cowsay node -p \
  "process.env.PATH.split(':').find(p => p.includes('_npx'))"

これにより、次のようなパスが返されます。

/Users/john/.npm/_npx/8f497369b2d6166e/node_modules/.bin

Windowsでは、次を使用できます(1行が2つに分割されています)。

npx --package=cowsay node -p
  "process.env.Path.split(';').find(p => p.includes('_npx'))"

これにより、次のようなパスが返されます(単一のパスが2行に分割されています)。

C:\Users\jane\AppData\Local\npm-cache\_npx\
  8f497369b2d6166e\node_modules\.bin

npxのキャッシュは、npmがインストールするモジュールに使用するキャッシュとは異なることに注意してください。

両方のキャッシュの親ディレクトリは、以下で確認できます。

npm config get cache

npmキャッシュの詳細については、npmドキュメントを参照してください。

npxキャッシュとは対照的に、データはnpmキャッシュから削除されることはなく、追加されるだけです。Unixでは、次のようにサイズを確認できます。

du -sh $(npm config get cache)/_cacache/

Windows PowerShellでは、次のようになります。

DiskUsage /d:0 "$(npm config get cache)\_cacache"