前書き
この記事の目的
技術的な調査をしているとき、解説文に出てきている用語の意味や、その文脈での意味合いが掴みきれずに、なんとなくで読み進めていくことってありませんか?
なんとなくで読み進めていくから、最後の方はほとんどが ”なんとなく” の理解になっていて、どこまで行っても分かった ”つもり” にしかなれないような、そんなあなた、そして、そんな私自身のための記事です。
できるだけ補足をつけていくので立ち止まりながらゆっくり読むような記事にできればと思います。
前提
この記事ではNode.jsを用いた開発を対象にしています。
(私はそれ以外にあまり触れたことがないので)
「依存関係」とは何を指すのか
そもそも論になりますが、
「依存関係」
この用語がなんとも初心者にはわかりにくいですよね。
まずは例を挙げます。
例えば、あなたが「ペンギン」というアプリを開発しているとします。
「ペンギン」はReact.jsを用いて開発しており、デザインはBootstrapというツールを使用しています。
React.jsを用いて開発しているわけですから、当然、「ペンギン」はReactが存在していないと正常に動いてくれません。
つまり、「ペンギン」はReactに ”依存している” と言うことができます。
また、デザインはBootstrapがいい感じにしてくれるので、「ペンギン」はBootstrapにも 依存 しています。
その上で、BootstrapにはReactでの使用を前提としたツールセットのようなものも存在しているので、それを使用するとしたら、BootstrapもReactに依存していると言うことができるかもしれません。
イメージとしてはこんな感じ。
この一連の関係性のことを「依存関係」と言うのです。
「依存関係」は誰がどのように管理するのか
依存関係というものが何を指すのかが分かったところで、
「でもそれってどう管理しているの?」
という疑問に出会うかもしれません。
Node.jsでの開発では、package.json
というファイルでそれを管理します。
package.json
きっと皆さんが目にしたことのあるファイル名が出てきましたね。
「package.json とは」でググると最初にこんな説明が出てきます。
package.jsonはNode.jsプロジェクトにおける依存関係管理やスクリプトの定義に必要なファイルです。 外部パッケージの管理、バージョンの指定、プロジェクトの情報の記述など、プロジェクトの一貫性と管理を助ける重要な役割を果たします。
引用元:https://gk-fe.com/article/about-packagejson/
今の段階では
- 外部パッケージの管理
- バージョンの指定
この二つができるファイルだと思ってもらえればいいです。
ここでいうパッケージというのが、前述の「ペンギン」におけるReactやBootstrapに該当します。
このファイルは、プロジェクトを作成する際にターミナルやコマンドプロンプトで
npm init
などと入力すると勝手に作成されます。
Reactの雛形を作るときなんかは
npx create-react-app my-react-app
みたいにしてもちゃんと作成されます。
せっかくなので、npx create-react-app my-react-app
で作成したプロジェクトのpackage.json
を確認してみましょう。
{
"name": "my-react-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
色々書いてありますが、今回重要なのはこの部分です。
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
dependencies
を和訳すると「依存関係」です。
つまり、これが依存関係を管理している部分です。
dependencies
では、ここでどのようにして依存関係を管理しているのでしょうか?
それは先ほどの
- 外部パッケージの管理
- バージョンの指定
を決まった形式で記述して管理している、ということになります。
一例として
"react": "^18.3.1",
を見てみましょう。
これは「Reactのバージョン18.3.1を使う」という指定です。
つまり、
"外部パッケージ名": "バージョン",
ということになります。
つまり、依存関係を管理するということは、
「それぞれのパッケージのバージョンを適切に管理すること」
ということもできるかもしれません。
package.jsonとは、
「必要なパッケージの名前とバージョンのリスト」
だと思ってくれれば大丈夫です。
パッケージをインストールする
では、そのリストをもとに実際にパッケージをインストールするのは誰なのでしょうか?
Node.jsにはその辺りをカバーしてくれる便利なシステム「npm」が備わっています。
使い方はとても簡単。
ターミナルやコマンドプロンプトで
npm install
というコマンドを入力するだけです。
Node.jsさえ入っていれば正常にインストールが走ります。
node_modules
npm install
を実行すると、きっとあなたのプロジェクトにはpackage-lock.json
というファイルとnode_modules
というフォルダが生成されるはずです。
今回重要なのはnode_modules
なので、package-lock.json
の細かい説明は省きます。
補足:package-lock.jsonについて
本題からズレるので、package-lock.jsonについての説明は省きますが、詳しく知りたい方には下記の記事がおすすめです。
node_modules
とは package.json
を元にしてインストールされる各種パッケージがインストールされるディレクトリ先のことです。
Node.jsがあなたの作成したpackage.json
の依存関係リストをもとにして、実際のパッケージをネットワークを介してnode_modules
の中に格納します。
これだけでは曖昧な理解になる方もいるかもしれないので、例えてみます。
イメージとしては倉庫のようなものをイメージするといいかもしれないです。
Node.jsは注文(npm install
)を受け付けると、発注リスト(package.json
)をもとにインターネット上から商品(パッケージ)を探しに行って、倉庫(node_modules
)に格納する、といった流れです。
あなたの開発プロジェクトでそれぞれのパッケージが必要になったときには、このnode_module
を参照します。
ここでよくある疑問としては、
「リストの管理なんかせずに、最初からパッケージを直接node_modules
に格納しちゃえばいいじゃん」
という疑問だと思います。
その理由としては、
「後々面倒になるかもしれないから」
です。
先ほどの例のように2.3個しかパッケージがなければ実はそれほど面倒にはなりません。しかし、管理するパッケージが20個や30個になったら場合を想像すると、その面倒さと、リストと倉庫を分ける理由もわかります。
package.json
でパッケージをリスト管理するとき、パッケージの名前とともにバージョン情報を管理していましたね。それはつまり、パッケージにおいてバージョンとは非常に重要な情報であることを指します。
バージョンが重要な情報ということは、
- バージョンが変わる可能性があるということ
- バージョンが変われば、パッケージの中身も変わること
が想像できます。
実際に、パッケージは適切に管理されていればいるほどアップデートが頻繁に発生します。
その内容は軽微な修正から、大幅な機能更新、重要なセキュリティ問題の解決など、多岐にわたります。
そういったものを確認し、毎回自分のプロジェクトのパッケージを手動で更新するのは非常に面倒であり、多分、ミスも発生します。
そのために、リストと倉庫というふうに分離させることで、管理を簡単にしています。
最後に
ここまで読めば、
- 依存関係
- package.json
- node_modules
などがそれぞれどんなものなのかがある程度わかったかと思います。
皆さんのプログラミングライフのささやかな手助けになれたら幸いです。
※
内容に指摘や補足がありましたら、適宜修正・補足の追加を行いますので、ぜひご指摘ください。