yarn install
の代わりにnpm install
を強制的に使用したい。 npm install
でエラーを発生させたい。 package.json
で何をすればよいですか?
UPDATE:Alexanderの答え がより良い解決策です。私は後世のために私の答えをそのまま残しています。私の答えの元々のポイントは、すべてのプラットフォームで機能するはずの小さなノードスクリプトを実行できることを示すことでした。
プレインストールスクリプトでは、すべてのプラットフォームで機能するミニノードスクリプトを実行できますが、pgrep
(およびその他の一般的な* nixコマンドと演算子)などは、Windows10が広く採用されるまでWindowsでは機能しません。 。
以下のスクリプトをNode v4.7.0(npm v2.15.11)およびNode v7.2.1(npm v3.10.10)でテストしました。動作すると思います。現在実行中のプロセスの環境変数をチェックすることで機能します-npm_execpath
は現在実行中の「npm」スクリプトへのパスです。yarnの場合は/path/to/yarn/on/your/machine/yarn.js
を指す必要があります。
"scripts": {
"preinstall": "node -e \"if(process.env.npm_execpath.indexOf('yarn') === -1) throw new Error('You must use Yarn to install, not NPM')\""
}
Npmスクリプトの詳細については、こちらをご覧ください: https://docs.npmjs.com/misc/scripts
npm_execpath
環境変数に関する限り、文書化されていませんが、これから変更されることはないと思います。 npm
の複数のメジャーリリースが出回っていますが、「これにはもっと良い名前があります」テストに実際には合格していません。
他の回答と同様に、 preinstall
script を使用して環境を確認することをお勧めします。別のnpmプロセスが実行されている場合に誤検知が発生しないポータブルソリューションの場合、node -e 'JS_CODE'
を使用するのがおそらく最良のオプションです。
そのJSコードでは、以下を使用してパッケージマネージャーのパスを確認できます。
process.env.npm_execpath
NPMで使用されるyarn.js
と比較して、Yarnのバイナリはnpm-cli.js
です。次のような正規表現を使用して、この文字列がyarn.js
で終わることを確認できます。
/yarn\.js$/
この正規表現を使用することで、ファイルシステムの以前のどこかで誤って一致することがないようにすることができます。ほとんどの場合、yarn
はファイルパスに表示されませんが、確信が持てないことはありません。
最小限の例を次に示します。
{
"name": "test",
"version": "1.0.0",
"scripts": {
"preinstall": "node -e 'if(!/yarn\\.js$/.test(process.env.npm_execpath))throw new Error(\"Use yarn\")'"
}
}
もちろん、ユーザーはJSONを編集するか、--ignore-scripts
オプションを使用して、このチェックを回避することができます。
npm install --ignore-scripts
preinstall フックをいくつかのシェルスクリプトと一緒に使用して、これを実現できます。
sample package.json:
"scripts": {
"preinstall": "pgrep npm && exit 1"
}
このためのCLIを含むモジュールをリリースしました(npm preinstall
スクリプトに役立ちます): https://github.com/adjohnson916/use-yarn
また、CIでyarn.lock
の変更が欠落していないかどうかを確認するために、 Danger のヘルパーをリリースしました: https://github.com/adjohnson916/danger-yarn-lock
こちらの説明も参照してください。
パッケージがyarnまたはnpmのどちらでインストールされているかを簡単にテストしたい場合は、OS Xで機能したので、 Alexander O'Maraの回答 を少し調整しました。
_"scripts": {
"preinstall": "if node -e \"process.exitCode=!/yarn\\.js$/.test(process.env.npm_execpath)\" ; then echo yarn ; else echo npm ; fi",
"postinstall": ""
}
_
この短いスニペットでは、かなりの数の概念が発生しています。
_\\.
_部分はエスケープされ、_\\
_は_\
_になり、適切にエスケープされた_\.
_になり、正規表現の期間が検出されます。
_process.exitCode=
_は、プロセスの終了コードを設定するために使用でき、Node.jsの非同期性により、process.exit(N)
を呼び出すよりも安全です。
Alexanderの例 では、throw new Error(\"Use yarn\")
によりノードがコード1で終了し、スタックトレースがstderr
に出力されました。コンソールでこれらを実行して、それがどのように機能するかを確認できます:node -e 'throw new Error("Oops")'
およびnode -e 'throw new Error("Oops")' 2> /dev/null
(stderr
ストリームを_/dev/null
_に転送します)。次に、_echo $?
_(最後の終了コードを出力します)を使用して、終了コードが1であることを確認できます。
シェルの_if XXXX ; then YYYY ; else ZZZZ ; fi
_条件付きロジックは、XXXX
の終了コードをチェックし、then
の場合に0を返します(他の値はelse
の場合に行きます)。したがって、正規表現が_yarn.js
_の最後に_process.env.npm_execpath
_を検出すると、trueを返します。ノードプロセスがコード0で終了し、if
を満たすように、これを否定する必要があります。
正規表現の結果をconsole.log()
して、シェルの出力を比較することもできます(これはもう少し冗長です)。これを行う方法の例を次に示します。 https://unix.stackexchange.com/a/52801 および https://superuser.com/a/688902
_true ;
_または_false ;
_を任意のシェルステートメントに追加して、終了コードを手動で設定できます。たとえば、_true ; echo $?
_または_false ; echo $?
_を試すことができます。
必要がない場合は、_else echo npm ;
_部分を完全に省略することもできます。
これらすべてが邪魔にならないので、_echo yarn
_と_echo npm
_の部分を他のコマンドに置き換えることができます。たとえば、_(echo yarn)
_やecho $(echo yarn)
のようなサブシェルに複数のコマンドを配置できます。
私の場合、パッケージの1つがインストールされているが、糸の下にバグがあるという問題を回避する必要があったため、成功した場合は_npm install --ignore-scripts
_を実行する必要がありました。これはおそらく本番環境では決して行われるべきではありませんが、何かを行う必要がある場合や、将来使用されるパッケージマネージャーを制御できない場合は、命の恩人になる可能性があることに注意してください。
私はこれをWindowsで試したことがないので、誰かがそこで構文をテストできる場合は、機能するもので答えを更新します。 preinstall
スクリプトが、WindowsとMac/Linuxシェルの両方で同一であることが最善です。