web-dev-qa-db-ja.com

Node module?のnpminstallの代わりにyarninstallを強制します

yarn installの代わりにnpm installを強制的に使用したい。 npm installでエラーを発生させたい。 package.jsonで何をすればよいですか?

14
Matt - sanemat

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の複数のメジャーリリースが出回っていますが、「これにはもっと良い名前があります」テストに実際には合格していません。

15
Ryan Wheale

他の回答と同様に、 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
9

preinstall フックをいくつかのシェルスクリプトと一緒に使用して、これを実現できます。

sample package.json:

  "scripts": {
    "preinstall": "pgrep npm && exit 1"
  }
1
d3ming

このためのCLIを含むモジュールをリリースしました(npm preinstallスクリプトに役立ちます): https://github.com/adjohnson916/use-yarn

また、CIでyarn.lockの変更が欠落していないかどうかを確認するために、 Danger のヘルパーをリリースしました: https://github.com/adjohnson916/danger-yarn-lock

こちらの説明も参照してください。

1
AndersDJohnson

パッケージが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/nullstderrストリームを_/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シェルの両方で同一であることが最善です。

1
Zack Morris