パッケージマネージャー周り(主にnpm)を整理してみました。
パッケージとは
ソフトウェアのコード、リソースをまとめたもの。
関数、クラス、変数、静的ファイルなどが含まれる。
要は便利な機能をパッケージ化して提供していて、開発者は関数、タグなどを呼んで使うだけで0-1で実装しないで済み、開発効率を上げられる。
例)時刻の操作(day.js)、グラフの描画(chart.js)など
*パッケージをライブラリと呼んでもOK
依存関係とバージョン管理
パッケージは他のパッケージを使用している事がある。これを 依存関係 と呼びます。
例)Expressは裏側で沢山パッケージを使用していて、更に複雑にバージョンが絡んでいる
そんな複雑な依存関係を人間が管理、解決するのは困難。
それをまとめていい感じに管理してくれるのがパッケージマネージャー
パッケージマネージャーとは
プログラムを一貫した方法でインストール、アンインストール、パッケージの依存関係を解決する流れをツールによって管理を自動化するシステム
パッケージマネージャーの種類:
JavaScript (Node.js)
npm
yarn=JavaScript (npmより高速、依存関係の解決でnpmより優れていて、安全性が高い)
pnpm=最新のJSのパケマネ
*npm, yarn複数のパッケージマネージャーを混在させるのはNG!
Python
pip
Ruby
Gems
以上言語ごとにあるけど、Mac OS用のbrew
とかもパッケージマネージャー
npmとは
Node Package Manager
の略
JavaScript (Node.js)のパッケージマネージャーのひとつ。
フロントエンド開発ではNode.js上で動くツールを多用するため、これらのツールのバージョン管理システムの必要性が出て、npmが登場した。
またnpmレジストリ(パッケージのプラットフォーム)というパッケージの公開、検索ができるサイトもある。
ここで公開されているパッケージはnpm
はもちろん、yarn
, pnpm
経由でもインストールができる。誰でもパッケージを公開できるので、危ないもの、更新されてないものもあるので、吟味が必要。
余談
過去のプロジェクトでサービスの核になる機能(複雑で肥大化していた)を切り出して別レポジトリに分けて、npmレジストリで公開し、外部ライブラリの様に扱う運用にした。
それが更新されると、npmインストールすれば最新が使えるという感じで管理がしやすくなった。
ただ一般公開されてしまっていることを懸念する声もあったので、今は違う運用に変えてるかもしれません。
package.jsonとは
Node.jsプロジェクトのパッケージ管理ファイルで、メタ情報(基本情報)や依存関係の定義が記述されていて、とても重要なもの。
npm, yarn, pnpmだろうと、このpackage.jsonが使われる(理由はyarn, pnpmはnpmと互換を持って作られてるから)
例)
Reactをインストールすると、package.jsonにreactだけ記載される
Reactが依存してるパッケージの詳細は後述するpackage.lock.jsonに記載される
"dependencies": {
"react": "18.2.0",
}
-devでインストールするケース:
ビルドしたらサーバーには置かなくていいパッケージ(製品そのものに不要、開発段階だけで使うもの)は、インストールコマンドに-dev
をつけてdevDependenciesに入れる。これでリリースビルドには含まれない。
例)ESLint, testツールなど
"devDependencies": {
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.23.0",
}
Node.jsはPCにインストールされて、そこにもpackage.jsonがある(見えない場所)グローバルインストールしたパッケージはそこに格納される
*グローバルインストール=PCの中のどこからでも使える
*通常はプロジェクトのディレクトリ内でローカルインストールをする
package.lock.jsonとは
package.jsonに記載されてるバージョンはざっくりとした範囲で書かれている
"dependencies": {
"vue": "^3.4.21"
}
^3.4.21
は、3.4.21以上という意味
そのため、チーム内で異なるタイミングでnpm installするとバージョンに差が出て衝突してしまう。
それを解決するためにpackge.lock.jsonが全パッケージの依存関係を解決した完全な情報を作り、バージョンは正確な値を固定で書いてくれる。URLなども記載されている。
→バージョンを固定(Lock)してチーム全員が同じバージョンを使うようにする
つまりパッケージのインストールはpackge.lock.jsonの中のバージョンを見て実行される
*package.lock.jsonがないプロジェクト初期の場合は、package.jsonを見てインストールして、package.lock.jsonを作成する
*yarnの場合はyarn.lockがこれに当たる
なぜわざわざ2つ分かれてるのか?
パッケージマネージャーがバージョン管理、依存関係の解決がしやすいという理由と、以下の理由で2つに分かれている。
package.json
人間が見て読めるし、編集する事も可能
packge.lock.json
npmが自動で管理する、量が多く複雑なので読みにくいし、触らない!
パッケージをインストールすると、裏側でそのパッケージが依存するパッケージもインストールされる
それらのバージョンの依存関係の解決をnpmがやってくれる
なので、開発中にpackge.lock.jsonに差分が出たらコミットしてOK
node modulesとは
パッケージそのものがここに入るので、大容量。
packge.lock.jsonがあれば再生可能なので、GitHubにあげないのが鉄板ルール。
不具合起こした時に、一回全部消して再インストールとかする事もよくある。