
YarnはFacebook、Google、Exponent、Tildeによって開発された新しいJavaScriptパッケージマネージャーです。公式発表に記載されているように、Yarn開発者が直面したnpmの問題解決を目的としています。
- インストールパッケージの速度および一貫性が不十分である
- npmではパッケージがインストール時にコードを実行することを許可しているため、セキュリティー上の問題がある
しかし、それほど驚かないでください。npmを完全に置き換えるわけではありません。Yarnはnpmレジストリからモジュールを取得する単なる新しいCLIクライアントで、レジストリ自体はなにも変わりません。現在でも、通常通りパッケージの取得および配布が可能です。
いますぐにこのYarnに飛びつくべきでしょうか。本記事ではnpmとYarnを比較し、どちらが自分に適しているか判断できる材料を提供します。
Yarn対npm:機能面の違い
一見すると、Yarnとnpmは似ているように思えます。しかし、詳細を理解するとどのように違うかが分かります。
yarn.lockファイル
npmもYarnもプロジェクトの依存オブジェクトをpackage.jsonファイルに記録しますが、ファイル内のバージョン番号が常に正しいとは限りません。代わりに、バージョン範囲の定義ができます。特定のメジャー、マイナーバージョンのパッケージを選択できますが、npmがバグを修正する最新パッチをインストールできるように許可する必要があります。
セマンティック バージョニングが理想的に運用されている状況では、パッチを適用しても互換性は損なわれません。しかし、残念なことに、常にセマンティック バージョニングが正しく運用されているとは限りません。npmが採用している方法だと、2つのマシンが同じpackage.jsonを使用している場合、異なるバージョンのパッケージをインストールしてバグが発生する可能性があります。
バージョンの不整合を防ぐために、インストールされている正しいバージョンをロックファイルで固定する必要があります。
Yarnは、モジュールが追加されるたびに、yarn.lockファイルを生成(または更新)します。package.jsonで定義された許可済みのバージョン範囲を維持している間、同一バージョンを別のマシンにインストールできます。
npmでは、npm shrinkwrapコマンドがロックファイルを同様に生成します。そして、Yarnが最初にyarn.lockを読み込むのと同じように、npm installがpackage.jsonを読み込む前にロックファイルを読み込みます。
ここで注目すべき違いは、npmがデフォルトではロックファイルを生成せず、npm-shrinkwrap.jsonが存在するときに更新するのみであるのに対し、Yarnは常にyarn.lockを生成し、更新するという点です。
並行インストール
npmやYarnがパッケージをインストールするたびに、一連のタスクが実行されます。npmではパッケージごとに、連続して実行されます。つまり、1つのパッケージのインストールが完了するのを待機してから、次のパッケージへと進みます。Yarnはタスクを並行して実行するので、パフォーマンスが向上しています。
比較のために、npmとYarnの両方でexpressパッケージをインストールしました。shrinkwrapとロックファイルを使わず、キャッシュをクリアにしてからインストールしています。合計42個のパッケージをインストールしました。結果は次のようになりました。
- npm:9秒
- Yarn:1.37秒
自分の眼を疑いました。同じ手順でもう一度インストールしても同様の結果でした。次に、gulpパッケージをインストールしました。結果的に195個の依存オブジェクトが得られました。結果は次のようになりました。
- npm:11秒
- Yarn:7.81秒
インストール時間の違いはインストールするパッケージの分量に大きく影響を受けるようです。どちらにしても、常にYarnがnpmの速度を上回っています。
出力をよりシンプルに
デフォルトでは、npmはとても詳細にコマンドを出力します。たとえば、npm install <package>を実行する際、インストール済みの全パッケージを何度も繰り返し一覧表示します。これに対して、Yarnのコマンド出力は繰り返しの一覧表示はしません。ほかのコマンド経由で詳細を取得できる場合は、適切な絵文字を使って情報をコンパクトに表示します(Windows環境の場合を除く)。
Yarn対npm:CLIの違い
機能の違い以外にも、Yarnにはさまざまなコマンドがあります。npmの一部のコマンドは削除され、そのほかのコマンドは修正され、さらに興味深いコマンドが追加されています。
yarn global
npmでは-gまたは--globalフラグを使用してグローバルな処理をしますが、Yarnのコマンドはglobalを接頭辞として付加する必要があります。npmと同様に、プロジェクト固有の依存オブジェクトをグローバルにインストールする必要はありません。
global接頭辞はyarn add、yarn bin、yarn ls、yarn removeにのみ機能します。yarn addを除いて、npmの相当するコマンドとまったく同じものです。
yarn install
yarn installはyarn.lockまたはpackage.jsonに記載された依存オブジェクトのみを記載された順番にインストールします。npm installコマンドは、package.jsonファイルから依存オブジェクトをインストールして、新しいパッケージを追加できるようにします
yarn add [–dev]
npm install <package>と同様に、yarn add <package>によって依存オブジェクトの追加およびインストールが可能になります。コマンド名からも分かるとおり、依存オブジェクトが追加されます。つまり、npmの--saveフラグのようにpackage.jsonファイル内のパッケージへの参照を自動的に保存します。Yarnの--devフラグは、npmの--save-devフラグのようにパッケージへの参照が自動的に保存されます。
yarn licenses [ls|generate-disclaimer]
yarn licenses lsは、インストール済みの全パッケージのライセンスを一覧にします。yarn licenses generate-disclaimerは、全パッケージのライセンスすべての内容を含む条項文を作成します。ライセンスの一部には、プロジェクト内にプロジェクトのライセンスを含む必要がある旨が明示される場合がありますが、このコマンドを使うと便利です。この記事の執筆時点でnpmには、これに相当するコマンドはありません。
yarn why
yarn whyを使うと、依存性グラフを確認し、パッケージがプロジェクトにインストールされた経緯を把握できます。そのパッケージは、明示的に追加されたものかもしれませんし、インストールしたパッケージの依存オブジェクトかもしれません。yarn whyはそうしたことを究明するのに役立ちます。
yarn upgrade [package]
yarn upgradeを使うと、package.jsonで規定されたバージョン規則に従って、パッケージを最新バージョンにアップグレードし、yarn.lockを再生成できます。npm updateに相当します。
興味深いことに、パッケージを指定すると最新バージョンに更新され、package.jsonで定義されたタグも更新されます。つまり、yarn upgradeコマンドでパッケージを新しいメジャーバージョンへ更新できます。
yarn generate-lock-entry
yarn generate-lock-entryコマンドは、package.jsonで設定された依存オブジェクトに基づき、yarn.lockファイルを生成します。npm shrinkwrapに相当します。yarn addやyarn upgradeを使用して依存オブジェクトを追加・アップグレードする際、ロックファイルが自動的に生成・更新されるため、このコマンドの使用には注意が必要です。
安定性と信頼性
Yarnは脱線せずにきちんと動くのでしょうか。リリース初日には多数の問題報告がありましたが、すでに驚くべき数の問題が解決されています。バグの発見、解決のために、コミュニティーが活発に活動していることが分かります。問題の数や種類を参照すると、Yarnは大部分のユーザーには安定してるように見えますが、特殊なケースにはまだ対応できていません。
多くの場合、パッケージマネージャーはプロジェクトに必須ですが、あくまでただのパッケージマネージャーであるということを忘れないでください。間違いがあった場合にパッケージを再インストールすることは難しくはありませんから、npmに戻る必要はありません。
今後の展開
もしかすると、読者のみなさんはNode.jsとio.jsにまつわる経緯を知っているかもしれません。かいつまんで説明すると、ガバナンスに関する意見の不一致からNode.jsから分岐したio.jsは、一部の献身的な人たちによって開発されました。io.jsはオープンガバナンスを採用しました。しかし、1年もたたないうちに、Node.jsとio.jsのチームは合意に達し、io.jsは再びNode.jsに合併され廃止されました。それが正しいかどうかは別として、多くのすぐれた機能がio.jsからNode.jsに導入されました。
npmとYarnについても似たようなパターンだと思っています。Yarnはチェスで言うフォーク(両取り)ではありませんが、npmの欠陥の一部を改善しています。Node.jsとio.jsのように、Facebook、GoogleやそのほかのYarnのコントリビューターにnpmの改善を手助けしてもらうように頼むというのはどうでしょうか。実現するかどうかは分かりませんが、そうなることを願っています。
いずれにせよ、Yarnの未来は希望に満ちています。コミュニティーは盛り上がりを見せていて、新しいパッケージマネージャーの取得も順調です。残念ながら、ロードマップが入手不可能なため、Yarnが今後どのように展開していくのかはまだ分かりません。
最後に
Yarnはnpmと比較して高い評価を得ています。ロックファイルは自由に手に入れられますし、パッケージのインストールはとても高速で、package.jsonに自動的に保存されます。また、Yarnのインストール、使用による影響は最小限で済みます。最初は1つのプロジェクトだけでYarnを試して、使い勝手を見極め、それからYarnを完全にnpmと置き換える方法があります。
いつかどこかのプロジェクトで、ぜひYarnを試してください。新しいソフトウェアのインストールや使用に慎重な場合は、数カ月試してください。結局のところ、npmは多くのプロジェクトで成果を収めており、ソフトウェア開発の世界において価値があることは間違いありません。
もし、パッケージのインストールの完了を待っている自分に気づいたら、移行ガイドに目を通す絶好のタイミングです。
※本記事はAdrian Sandu、Marcello La Rocca、Matt Burnett、Nuria Zuazo、Vildan Softicが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。
※2016.10.26:記事を更新し、コメントでの指摘事項に対応しました。
(原文:Yarn vs npm: Everything You Need to Know)
[翻訳:市川千枝/編集:Livit]
