
パッケージ管理方法を知る!〜パッケージマネージャーの仕組み編〜
みなさんこんにちは!
ワンキャリアでソフトウェアエンジニアをしていますアリックス・ファシャン(GitHub: AlixFachin)です。
最近、参加しているプロジェクトで依存関係のインストールとアップグレードを行う必要がありました。その際に参考になるブログ投稿やヘルプページがまだ少ないことに気づいたので、今回まとめてご紹介したいと思います。
このトピックは少し複雑なので、内容を2つの記事に分けることにしました。
第1弾の記事ではパッケージ管理の基本について説明し、第2弾の記事では依存関係のアップグレードの詳細と戦略について掘り下げていく予定です。
それでは早速始めていきましょう!
依存関係の基本的定義
本記事における依存関係とは
依存関係とは、自分が書いたコード内で他の誰かによって書かれたライブラリ(別のコード)を使用する際に生じる関係です。OSSの急速な拡大から、他の人が見つけた解決策を簡単に利用できるようになりました。
例えば、QRコードを生成したい場合、そのためのライブラリがあります。アニメーションを作成したい場合も、そのためのライブラリがあります。
短期的には、依存ライブラリを使用することで、コードをより早くリリースすることができます。しかし、長期的には、プロジェクト管理の負担が増えることになります。というのも、JavaScriptの世界は常に変化しており、言語やその他の技術の進化に合わせてライブラリを更新する必要があるからです。
こういった作業を支援するために設計されたプログラムで『パッケージマネージャー』というものがあります。
JavaScriptのパッケージマネージャーについて
パッケージマネージャーは、言語毎にそれぞれあります。例えば、Rustにはcargo、RubyにはBundlerがあります。
また、JavaScriptの世界には、主に3つのパッケージマネージャーがあり、npm、yarn、そしてpnpmです。これらは「依存関係マネージャー」とも呼ばれることもあります。
これらのパッケージマネージャーは、実際に「管理」するというよりは、主に、依存関係のインストールや削除に利用されています。
npmは、2010年にリリースされたオリジナルのパッケージマネージャーです。その名の通り「Node Package Manager」です。初期のバージョンでは、npmはかなり遅く、いくつかのセキュリティ問題が発見されました。それらは最近のバージョンで修正されています。ほとんどの開発者がnpmの構文を知っているため、新しいプログラマーがプロジェクトに参加する際のオンボーディングは少し楽になります。
yarnは、Meta社によって開発され、2016年にリリースされたパッケージマネージャーです。もともとはnpmの多くの欠点を補うために開発されました。npmとは異なるコマンドがあるため、慣れるのに少し時間がかかります。
pnpmは「強化された」npmであり、パッケージのインストール方法を変更し、中央リポジトリを使用します。これにより、同じ端末に複数のプロジェクトがある場合、インストールが非常に速くなることがあります。
この記事では、就活サービス ONE CAREERで使用しているyarnに焦点を当てます。
SemVerについて
Semantic Version (通称SemVer)はライブラリのバージョン番号に関する一連のガイドラインです。
各インポートされたパッケージは、その貢献者によってバージョンで管理されており、通常はドットで区切られた3つの数字(例: v 5.10.4)で表されます。
最初の数字は「メジャーバージョン」、2番目の数字は「マイナーバージョン」、最後の数字は「パッチバージョン」と呼ばれます。
パッケージのメンテナーが新しいバージョンをリリースすることを決定する際には、新機能の追加、バグ修正、ドキュメントの変更などが理由となります。そして新しいバージョン番号で新しいコードセットが利用可能になります。
メジャーバージョンやマイナーバージョンを増やすかどうかに関する義務はありませんが、「セマンティックバージョニング」と呼ばれる一連のガイドラインが存在し、ほとんどのライブラリがこれらのルールを遵守しています。ガイドラインはsemver.orgで読むことができます。
慣習として、マイナーまたはパッチバージョンを増やしても破壊的変更は引き起こされませんが、メジャーバージョンではしばしば破壊的変更が生じ、その結果、より注意が必要です。
バージョン範囲の指定
パッケージマネージャーは、バージョン範囲を示すために ~ および ^ 記号をよく使用します。
~1.2.3 は、同じパッチバージョン番号を持つすべてのバージョン、つまり 1.3.0 未満のすべてのバージョンを含みます。
^1.2.3 は、同じマイナーバージョン番号を持つすべてのバージョン、つまり 2.0.0 未満のすべてのバージョンを含みます。
SemVerを遵守していないライブラリ
実は全てのライブラリがSemVerを厳密に守っているわけではありません! 非常に人気がある一部のライブラリは、マイナーバージョンのアップグレードで破壊的変更を導入しない場合、またはメジャーバージョンのアップグレードでも破壊的変更がない場合があります(例: TypeScript)。そのため、ライブラリのバージョンをアップグレードするたびに、リリースノートを確認することを習慣にするのがおすすめです。
バージョン管理 - .lock ファイル
よくプロジェクトは「特定のバージョン」ではなく、「特定のバージョン範囲」を必要とします。これにより、同じチームの複数のメンバーが同じ依存関係のバージョンをインストールしていないという問題が発生する可能性があります。さらに、「依存関係の依存関係」を考慮に入れると、すぐに混乱と予測不能なバグ(「自分のパソコンで実行すると問題ないよ」などの発言)につながる可能性があります。
例を見てみましょう。プロジェクトに axios パッケージを必要としていて、
package.jsonに ~1.7.3と指定されているとします。
このパッケージの最新バージョンは 1.7.7です。つまり、プロジェクトを今インストールする人は理論的にはバージョン1.7.7を持っている可能性があり、あなたはまだ1.7.3を持っているかもしれません。もしバージョン1.7.6があなたのコードに破壊的変更を導入した場合はどうなるでしょうか?
この問題を解決するためには、実際にインストールされたライブラリのバージョン番号の追跡が必要です。これが .lock ファイルの目的です。yarn では yarn.lock ファイル、npm では package-lock.json です。.lock ファイルには、プロジェクトのすべての依存関係についてインストールされた正確なバージョンが記録されています。そのため、このファイルの内容に従ってプロジェクトをインストールする人は、まったく同じバージョン番号をインストールすることになります。
主なyarnコマンド
パッケージマネージャーの目的がわかったところで、主なコマンドを見ていきましょう。ここでは yarn に焦点を当てますが、ほとんどの場合、npm にも同様のコマンドがあります。
これらのコマンドをあなたのリポジトリで試してみて、その結果を自分で確認することをお勧めします。npm install や npm remove の先には、複雑な世界が広がっています...。
基本なコマンド
yarn と yarn install
これはリポジトリをクローンした後に最初に実行するコマンドです。パッケージマネージャーは yarn.lock ファイルを読み込み、正確なバージョン番号で対応する依存関係をインストールします。
パッケージマネージャーにはインストールを速くするためのさまざまな方法がありますが、その詳細はこの記事の範囲を超えています。
yarn add , yarn remove
これらの2つのコマンドは、プロジェクトから依存関係を追加または削除するために使用されます。
インストールするバージョン番号を指定することができます。
yarn list
これにより、すべての依存関係とその依存関係がインストールされたバージョン番号とともに表示されます。
yarn list | wc -l を実行すると、プロジェクトにインストールされたライブラリの総数を確認できますが、それは非常にしばしば思っていたよりも多いです!
依存関係を管理するためのコマンド
yarn outdated
このコマンドは毎週実行することをお勧めします。これにより、新しいバージョンがリリースされたパッケージを表示し、リリースがメジャーかマイナーかを示す色分けがされています。
パッケージのホームページへのURLも含まれていて、非常に便利です。このURLを開くと、リリースノートやREADMEを確認することができます。

yarn audit
このコマンドは、依存関係をセキュリティの観点から確認することができます。
セキュリティ脆弱性の報告が提出されたパッケージと、その問題を修正するバージョンを一覧表示します。
もちろん、yarn audit に問題がリストされていないからといって、プロジェクトが100%安全であることを意味するわけではなく、リストされた脆弱性が必ずしもあなたに適用されるわけではありません。
しかし、どのパッケージを優先してアップグレードすべきかを決定する際の緊急性や優先順位の判断材料を与えてくれます。

yarn why
時には、古いパッケージや監査の問題があり、特定の依存関係の使用を覚えていないことがあります。
yarn why は、この依存関係に関する情報を表示します。つまり、プロジェクト自体によってインポートされたライブラリなのか、それともプロジェクトの依存関係の1つによって必要とされているのかを示します。
このコマンドの実行は、プロジェクトから依存関係を安全に削除できるかどうかを確認したり、依存関係をアップグレードする際の潜在的な問題を予測するのに役立ちます。

yarn upgrade-interactive
このコマンドを実行すると、yarnが利用可能なバージョンのリストを表示し、アップグレードするバージョン番号を選択できるようになります。
まとめ
この記事では、パッケージ管理ツールとは何か、なぜそれらが作られたのか、そしてその主な機能について見てきました。これらのコマンドをいろいろと試してみて、依存関係やその管理方法に慣れることを強くお勧めします。
私たちのツールボックスにどのようなツールがあるかを理解したところで、次回の記事ではそれらをどのように使うか、つまりJavaScriptでプロジェクトの依存関係を実際に管理する方法を見ていきます。
「人の数だけ、キャリアをつくる。」
ワンキャリアではミッション実現のために、事業・プロダクト開発を推進させる仲間を募集しています。弊社のエンジニア組織にご興味を持っていただけた方は、採用情報もチェックいただけると嬉しいです!
▼ワンキャリアのエンジニア組織のことを知りたい方はまずこちら
▼カジュアル面談を希望の方はこちら
▼エンジニア求人票