【npm】概念、コマンドについて調べました。

## ◆はじめに

「`npm`って何？」「`package.json`って？」と、ふんわりした状態だったので、調べた自分のメモをまとめておきます。

## ◆目次
[◆はじめに](#はじめに)
[◆目次](#目次)
[◆Node.jsとは](#nodejsとは)
[◆npmとは](#npmとは)
　[1. オンライン上のパッケージレジストリ](#1-オンライン上のパッケージレジストリ)
　[2. 上記パッケージレジストリとやりとりするためのCLI](#2-上記パッケージレジストリとやりとりするためのcli
)
[◆特定のパッケージをインストールしてプロジェクトを作成する手順](#特定のパッケージをインストールしてプロジェクトを作成する手順)
　[1. Node.jsをインストール](#1-nodejsをインストール)
　[2. プロジェクトを作成](#2-プロジェクトを作成)
　[3. パッケージのインストール（特定のパッケージを指定）](#3-パッケージのインストール特定のパッケージを指定)
　[4. プログラムを書く](#4-プログラムを書く)
　[5. 実行コマンド](#5-実行コマンド)
[◆package.json、package-lock.jsonを元にパッケージをインストールする](#packagejsonpackage-lockjsonを元にパッケージをインストールする)
　[1. package.jsonを元にパッケージをインストール](#1-packagejsonを元にパッケージをインストール)
　[2. package-lock.jsonを元にパッケージをインストール](#2-package-lockjsonを元にパッケージをインストール)
[◆その他のよく使うnpmコマンド](#その他のよく使うnpmコマンド)
　[1. パッケージのバージョン確認](#1-パッケージのバージョン確認)
　[2. パッケージのアップデート](#2-パッケージのアップデート)
　[3. パッケージのアンインストール](#3-パッケージのアンインストール)
[◆最後に](#最後に)
[◆参考](#参考)

## ◆Node.jsとは

- JavaScriptのサーバー上の実行環境
- 処理を非同期で実行できる
- 外部のパッケージを読み込んで利用できる
>これまでWebブラウザの中だけで動いていたJavaScriptという言語のエンジン部分をWebブラウザから切り離し、独立したプログラムとして実行できるようにしたのがNode.jsなのです。

([「Node.js超入門 第3版」](https://www.amazon.co.jp/Node-js%E8%B6%85%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88-%E6%8E%8C%E7%94%B0%E6%B4%A5%E8%80%B6%E4%B9%83/dp/479806243X/ref=asc_df_479806243X/?tag=jpgo-22&linkCode=df0&hvadid=342357386046&hvpos=&hvnetw=g&hvrand=15033111640526044598&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009545&hvtargid=pla-917964847122&psc=1&th=1&psc=1)より引用）

## ◆npmとは

- `Node Package Manager`の略
- 次の2つの意味合いがある

### 1. オンライン上のパッケージレジストリ

世界中で開発されたNode.js のパッケージがまとめて公開されている場所。
（パッケージ=Node.jsの機能を拡張するプログラム。モジュールとも呼ばれる）
自分でコードを書かなくても、パッケージを利用することでその機能をより簡単にプロジェクトに追加することができる。

https://www.npmjs.com/

次の2.と区別するため大文字でNPMと表現されることも（この記事でもそうします）

### 2. 上記パッケージレジストリとやりとりするためのCLI

- CLI =コマンドラインインターフェース
- 「Node.jsのパッケージ管理システム」と定義される場合はこちらの意味合いで使われている
- コマンドを実行することにより、1.のNPMパッケージレジストリからパッケージのインストール、アップデート、アンインストールなど、様々なことができる
- １つのパッケージは他の複数のパッケージに依存し、そのパッケージがまた複数の他のパッケージに依存して…と依存関係が連鎖しているが、１つ１つ個別に対応しなくても、コマンドで全ての依存関係を解決してくれる
- Node.jsと一緒にインストールされる



## ◆特定のパッケージをインストールしてプロジェクトを作成する手順
### 1. Node.jsをインストール

以下のサイトからインストールできます。

https://nodejs.org/ja/

※OSによりインストール方法が違ったり、Node.jsのバージョン管理ツールを利用してインストールしたりしますが今回は割愛します（[参考サイト一例](https://www.sejuku.net/blog/72545)）

バージョンを確認。
```sh
$ node -v
v16.13.0
        
$ npm -v
8.1.0
```

### 2. プロジェクトを作成

まず、プロジェクトのディレクトリを作成し、その中に移動します。
プロジェクト名が`npm_app`とすると↓
```sh
$ mkdir npm_app
$ cd npm_app
```

プロジェクトで`npm`を利用するには、以下のコマンドで初期化します。

```sh
$ npm init
$ npm init -y  # 質問&回答を省略する場合
```

- -yオプションをつけない場合、`package.json`に記述する内容を質問されるが、特に指定がなければ全ての質問にEnterキーを押してOK
- プロジェクト名はコマンドを実行したディレクトリ名となる（プロジェクト名は変更可能）
- `package.json`ファイルがプロジェクト内のディレクトリに作成される


```
npm_app   
　└── package.json
```

:::note
package.jsonとは

- パッケージのバージョン管理を行うファイル
- プロジェクトで使用するパッケージとバージョン範囲が記載される
- Git管理に含める
:::

作成された`package.json`の初期値（質問&回答を省略した場合）

```json:package.json
{
  "name": "npm_app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```
`main`の`index.js`がプロジェクトを実行する時のエントリポイントとなります。
`index.js`は同じディレクトリ内に自分で作成します。

```sh
$ touch index.js
```

```
npm_app
├── index.js  // 作成した
└── package.json
```

### 3. パッケージのインストール（特定のパッケージを指定）

以下のコマンドで、NPMレジストリからパッケージをインストールして`node_modules`ディレクトリに保存します(`node_modules`ディレクトリがない場合は作成されます）
```sh
npm install <パッケージ名>          # 最新のバージョン
npm install <パッケージ名@バージョン> # 特定のバージョン
npm install -g <パッケージ名>       # グローバルにインストール ※各パッケージのバージョン依存が大きいため非推奨
npm install -D <パッケージ名>       # 開発環境のみで使用するパッケージをインストール（eslintなど）
```
- `npm install`のエイリアス→`npm i`、`npm add`など
- パッケージ名をスペースで区切り、複数のパッケージを指定することもできる
- インストール対象のパッケージが依存するパッケージがある場合は自動でインストールされる


では、実際にNPMからパッケージをインストールしてみます。
何でもいいのですが、今回は`node-fetch`をインストールします。

https://www.npmjs.com/package/node-fetch

> node-fetch モジュールは、Node.js アプリで Web ブラウザと同様の fetch 関数を扱えるようにするためのライブラリです。 これを使うと、Promise ベースの HTTP 通信を行うことができます。

「[node-fetch モジュールを使用して HTTP 通信を行う](https://maku77.github.io/nodejs/net/node-fetch.html) 」より

では、インストールします。
```sh
npm install node-fetch
```


すると、`package.json`にパッケージ情報が追記され、
`node_modules`ディレクトリ、`package-lock.json`ファイルが新たに作成されます。

```
npm_app
├── node_modules // 作成された
　　　└── パッケージのディレクトリ群
├── index.js
├── package-lock.json // 作成された
└── package.json  // 追記された
```

まず、`package.json`を確認すると、`dependencies`というプロパティが追加され、その値として`node-fetch`というパッケージ名とそのバージョン範囲が記載されています。
```json:package.json
{
  "name": "npm_app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-fetch": "^3.3.0"
  }
}
```
次に、`package-lock.json`を見てみます。

:::note
package-lock.jsonとは

- 実際にインストールしたパッケージ（パッケージが依存するパッケージ含む）とそのバージョンが記載される
- このファイルが存在することで、複数の開発者が全く同じ開発環境を再現できる
- Git管理に含める
:::

<details><summary>作成されたpackage-lock.jsonの中身はコチラ（長いのでクリックで参照）</summary><div>

```json:package-lock.json
{
  "name": "npm_app",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "npm_app",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "node-fetch": "^3.3.0"
      }
    },
    "node_modules/data-uri-to-buffer": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
      "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
      "engines": {
        "node": ">= 12"
      }
    },
    "node_modules/fetch-blob": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
      "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/jimmywarting"
        },
        {
          "type": "paypal",
          "url": "https://paypal.me/jimmywarting"
        }
      ],
      "dependencies": {
        "node-domexception": "^1.0.0",
        "web-streams-polyfill": "^3.0.3"
      },
      "engines": {
        "node": "^12.20 || >= 14.13"
      }
    },
    "node_modules/formdata-polyfill": {
      "version": "4.0.10",
      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
      "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
      "dependencies": {
        "fetch-blob": "^3.1.2"
      },
      "engines": {
        "node": ">=12.20.0"
      }
    },
    "node_modules/node-domexception": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/jimmywarting"
        },
        {
          "type": "github",
          "url": "https://paypal.me/jimmywarting"
        }
      ],
      "engines": {
        "node": ">=10.5.0"
      }
    },
    "node_modules/node-fetch": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
      "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
      "dependencies": {
        "data-uri-to-buffer": "^4.0.0",
        "fetch-blob": "^3.1.4",
        "formdata-polyfill": "^4.0.10"
      },
      "engines": {
        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/node-fetch"
      }
    },
    "node_modules/web-streams-polyfill": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
      "engines": {
        "node": ">= 8"
      }
    }
  },
  "dependencies": {
    "data-uri-to-buffer": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
      "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA=="
    },
    "fetch-blob": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
      "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
      "requires": {
        "node-domexception": "^1.0.0",
        "web-streams-polyfill": "^3.0.3"
      }
    },
    "formdata-polyfill": {
      "version": "4.0.10",
      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
      "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
      "requires": {
        "fetch-blob": "^3.1.2"
      }
    },
    "node-domexception": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
    },
    "node-fetch": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
      "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
      "requires": {
        "data-uri-to-buffer": "^4.0.0",
        "fetch-blob": "^3.1.4",
        "formdata-polyfill": "^4.0.10"
      }
    },
    "web-streams-polyfill": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
    }
  }
}
```
</div></details>

最後に`node_modules`です。

:::note
node_modulesとは

- インストールしたパッケージの実態が入っている
- Gitでは管理しない（パッケージはプロジェクトとは独立して管理する）
:::

中身を見てみると、`node_fetch`や、それが依存するパッケージ群がインストールされているのが確認できます。

Gitで管理しない理由としては、パッケージを追加していくことにより膨大なデータ量となってしまうため、また、パッケージのアップデートや依存関係の変更のたびに都度パッケージのコードまでGitで管理するのは大変なためです。

開発者は、`package.json`、`package-lock.json`が存在すれば、npmコマンドを使ってパッケージの依存関係を再構築できます。
（これが`package.json`、`package-lock.json`の存在意義です）

では、`node_modules`をGitの管理から外しておきます。

```sh
$ touch .gitignore
```

```
npm_app
├── node_modules
　　　└── パッケージのディレクトリ群
├── .gitignore // 作成した
├── index.js
├── package-lock.json
└── package.json
```
`.gitignore`に以下を追加します。
```:.gitignore
/node_modules
```

### 4. プログラムを書く

では、この状態で`node-fetch`パッケージを利用した簡単なプログラムを`index.js`に書いて実行してみます。
今回は、おしりたんていのキャラクターのページのソースを取得して出力します（※もしご自身で試される場合はURLを好きなものに変えてください）

https://www.oshiri-tantei.com/character/


パッケージは`require`または`import`で読み込みます（モジュールの読み込み形式、環境により異なります）
最低限のコードとなりますが…今回は動かすことだけの確認なので。

```js:index.js
import fetch from "node-fetch"; // パッケージの読み込み

fetch("https://www.oshiri-tantei.com/character/")
  .then((res) => res.text())
  .then((body) => console.log(body));
```
`import`を使用する場合、`package.json`に`"type": "module"`を追記します。
```json:package.json
{
  "name": "npm_app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-fetch": "^3.3.0"
  }
}
```

では、この状態で実行します。

### 5. 実行コマンド
```sh:実行コマンド(1)
$ node .
```
カレントディレクトリを引数にすることにより、そのディレクトリに存在する`package.json`に記載されているmainプロパティのファイルが実行されます。

または、以下のようにファイル名を指定してもOK

```sh:実行コマンド(2)
$ node index.js
```

もしくは、以下のように`package.json`の`"scripts"`に`"start": "node index.js"`と登録しておくと…

```json:package.json
{
  "name": "npm_app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-fetch": "^3.3.0"
  }
}
```
以下でも実行することができます。
```sh:実行コマンド(3)
$ npm start
# もしくは
$ npm run start
```

<details><summary>取得結果はコチラ（長いのでクリックで参照）</summary><div>

```html
<!DOCTYPE html>
<html xml:lang="ja" lang="ja">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
  <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,user-scalable=no,shrink-to-fit=yes">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="imagetoolbar" content="no" />
<link rel="shortcut icon" href="/favicon.ico">
<meta http-equiv="x-ua-compatible" content="IE=edge" />
<title>キャラクター | おしりたんてい | アニメ公式ホームページ</title>
<meta name="description" content="アニメ「おしりたんてい」NHK Eテレにて好評放送中！エクセレントな推理と必殺技でどんな事件もププッと解決！是非お楽たのしみください！放送時間は(土)Eテレ 午前９:００～９:２０、(木)Eテレ 午後６:５５～７:１５です。">
<meta name="keywords" content="おしりたんてい,アニメ,東映,東映アニメーション" />
<meta property="og:title" content="キャラクター | おしりたんてい | アニメ公式ホームページ" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.oshiri-tantei.com/character/" />
<meta property="og:image" content="http://www.oshiri-tantei.com/ogp2.jpg">
<meta property="og:description" content="アニメ「おしりたんてい」NHK Eテレにて好評放送中！エクセレントな推理と必殺技でどんな事件もププッと解決！是非お楽たのしみください！放送時間は(土)Eテレ 午前９:００～９:２０、(木)Eテレ 午後６:５５～７:１５です。" />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:domain" content="https://www.oshiri-tantei.com/character/">
<meta name="twitter:description" content="アニメ「おしりたんてい」NHK Eテレにて好評放送中！エクセレントな推理と必殺技でどんな事件もププッと解決！是非お楽たのしみください！放送時間は(土)Eテレ 午前９:００～９:２０、(木)Eテレ 午後６:５５～７:１５です。">
<meta name="twitter:image" content="http://www.oshiri-tantei.com/ogp2.jpg">

<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c:wght@400;500;700;800;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/css/jquery.fancybox.css">
<link rel="stylesheet" href="/assets/css/slick.css">
<link rel="stylesheet" href="/assets/css/slick-theme.css">
<link rel="stylesheet" href="/assets/css/style.css">

<script src="/assets/js/jquery-3.6.0.min.js"></script>
<script src="/assets/js/jquery.fancybox.min.js"></script>
<script src="/assets/js/lazyload.js"></script>
<script src="/assets/js/slick.min.js"></script>
<script src="/assets/js/script.js"></script>

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-K3755S4');</script>
<!-- End Google Tag Manager --></head>
<body class="character">
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-K3755S4"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->


<header id="header">
  <div class="headerInr">
    <div class="logo">
      <a href="/index.html"><img src="/assets/img/header/img_logo.png" alt="おしりたんてい"></a>
    </div>
    <div class="menu">
      <div class="menuInr">
        <a href="" class="btnOpen">
          <img src="/assets/img/common/arw_top.svg" alt="" class="ico">メニューをひらく
        </a>
        <h2 class="tit">
          メニュー
        </h2>
        <nav>
          <ul>
            <li><a href="/info/"><img src="/assets/img/header/img_menu01.png" alt="おしりたんていとは？"></a></li>
            <li><a href="/onair/"><img src="/assets/img/header/img_menu02.png" alt="放送情報配信"></a></li>
            <li><a href="/character/"><img src="/assets/img/header/img_menu03.png" alt="キャラクター"></a></li>
            <li><a href="/story/"><img src="/assets/img/header/img_menu04.png" alt="ストーリー"></a></li>
            <li><a href="/goods/"><img src="/assets/img/header/img_menu05.png" alt="本・グッズ"></a></li>
            <li><a href="/events/"><img src="/assets/img/header/img_menu06.png" alt="イベント"></a></li>
            <li><a href="/movie/"><img src="/assets/img/header/img_menu07.png" alt="ムービー・ぬりえ"></a></li>
            <li class="SP"><a href="/index.html"><img src="/assets/img/header/img_menu_top.png" alt="トップページ"></a></li>
          </ul>
        </nav>
        <a href="" class="btnClose">
          <img src="/assets/img/common/ico_cross.png" alt="" class="ico">メニューをとじる
        </a>

        <div class="chara03">
          <img src="/assets/img/header/img_menu_chara.png" alt="">
        </div>
      </div>
    </div>
  </div>
  <img src="/assets/img/header/bg_header.png" class="bg" alt="">
</header><main id="main">
  <h1 class="tit">キャラクター</h1>
  <section class="character-main">
    <ul class="chara-tab">
      <li class="act">
        <a href="/character/"><img src="/assets/img/character/img_character01.png" alt="">おしりたんていじむしょ</a>
      </li>
      <li>
        <a href="/character/wankoro.html"><img src="/assets/img/character/img_character02.png" alt="">ワンコロけいさつしょ</a>
      </li>
      <li>
        <a href="/character/other.html"><img src="/assets/img/character/img_character03.png" alt="">とりまくひとびと</a>
      </li>
    </ul>
    <div class="character-list">
      <div class="character-wrap">
        <div class="character-item">
          <ul class="chara">
                                                              <li>
                <a href="/character/?char=char-oshiri">
                  <figure>
                    <img src="/assets/img/character/osiri/01_img.png" alt="" loading="lazy">
                  </figure>
                  <div class="name">おしりたんてい</div>
                                                                        <div class="cv">声：三瓶由布子</div>                </a>
              </li>
                                                              <li>
                <a href="/character/?char=char-brown">
                  <figure>
                    <img src="/assets/img/character/osiri/02_img.png" alt="" loading="lazy">
                  </figure>
                  <div class="name">ブラウン</div>
                                                                        <div class="cv">声：齋藤彩夏</div>                </a>
              </li>
                                                          </ul>
        </div>
      </div>
    </div>
  </section>
</main>

<footer id="footer">
        <ul class="banner">



                                <li><a href="https://www.poplar.co.jp/oshiri-tantei/" target="_blank"><img src="/assets/img/banner/bnr_poplar.jpg" alt="" ></a></li>
                <li><a href="https://www.toei-anim.co.jp/" target="_blank"><img src="/assets/img/banner/bnr_toeianim.jpg" alt=""></a></li>
                <li><a href="http://www.shonenjump.com/j/saikyo/oshiri-dandy/" target="_blank"><img src="/assets/img/banner/bnr_dandy.jpg" alt=""></a></li>
        </ul>
        <div class="copyright">&copy; トロル・ポプラ社／おしりたんてい製作委員会</div>

        <a href="" id="pagetop">
                <img src="/assets/img/footer/img_pagetop.png" class="PC" alt="">
                <img src="/assets/img/footer/img_pagetop_sp.png" class="SP" alt="">
        </a>
        <div class="sns">
                <ul>
                        <li><a href="https://twitter.com/intent/tweet?text=アニメ「おしりたんてい」公式ホームページサイト！アニメ化プロジェクト始動！&url=http://www.oshiri-tantei.com" rel=”nofollow” onClick="window.open(encodeURI(decodeURI(this.href)),'twwindow','width=550, height=450, personalbar=0, toolbar=0, scrollbars=1'); return false;"><img src="/assets/img/footer/ico_tw.png" class="tw" alt="Twitter"></a></li>
                        <li><a href="https://www.facebook.com/sharer/sharer.php?u=http://www.oshiri-tantei.com/" onclick="window.open(encodeURI(decodeURI(this.href)), 'FBwindow', 'width=554, height=470, menubar=no, toolbar=no, scrollbars=yes'); return false;" rel="nofollow"><img src="/assets/img/footer/ico_fb.png" class="fb" alt="Facebook"></a></li>
                                                <li><a href="http://line.naver.jp/R/msg/text/?アニメ「おしりたんてい」公式ホームページサイト！アニメ化プロジェクト始動！ http://www.oshiri-tantei.com" onclick="window.open(encodeURI(decodeURI(this.href)), 'LINEwindow', 'width=554, height=470, menubar=no, toolbar=no, scrollbars=yes'); return false;" rel="nofollow"><img src="/assets/img/footer/ico_line.png" class="line" alt="Line"></a></li>
                        <li><a href="https://www.youtube.com/watch?v=047VMJlBZxQ" target="_blank"><img src="/assets/img/footer/ico_youtube.png" class="youtube" alt="Youtube"></a></li>
                </ul>
        </div>


</footer><div id="modal" >
        <div class="modal_main">
                <div class="inner">
                                        </div>
        </div>
</div>

</body>
</html>
```
</div></details>

これで、Node.jsでパッケージを使ったプロジェクトが作成できました。

これだけだと、`package.json`、`package-lock.json`の意義が分かりづらいです…。

次に、他の開発者が上記プロジェクトの環境を構築する時のことを考えます。

## ◆package.json、package-lock.jsonを元にパッケージをインストールする

他の開発者が先ほど作成したプロジェクトをgit cloneした場合、`package.json`、`package-lock.json`は存在しますが、`node_modules`（=必要なパッケージ群の実態）はgitで管理していないので存在しません。
あくまでパッケージはNPMレジストリで管理されているのでnpmを使って必要なパッケージをインストールする必要があります。


その場合、以下の２つの方法があります。
1. `package.json`を元にパッケージのインストールする
2. `package-lock.json`を元にパッケージをインストールする

「どう違うの？」と私も最初は分からず…個人的に以下のように理解しました。

1. `package.json`を元にパッケージをインストールする
　→パッケージの依存関係をいい感じに解決した最新版をインストールしたいとき
2. `package-lock.json`を元にパッケージをインストールする
　→とにかく全く同じ環境を構築したいとき

### 1. package.jsonを元にパッケージをインストール
既存の`package.json`を元にインストールする場合、引数なしで以下のコマンドを実行します。

```sh
npm install
```
- `package.json`に記載されているバージョンの範囲で最新バージョンのパッケージ（依存関係も解決された状態）がインストールされる
- 上記により、`package.json`、`package-lock.json`が更新される（この変更は気にしなくて良いし、Gitの管理に含める）

NPMレジストリのパッケージやその依存するパッケージ…（依存関係）は、バグの修正や機能の改善などで日々アップデートされていきます。
`npm install`コマンドを叩くだけで自動的に新しい依存関係を取り込めるので便利です。

このコマンドにより、`package.json`、`package-lock.json`も変更されますが、その状態も他の開発者と共有したいので、Gitで管理します。

「`package.json`に記載のある範囲の最新バージョン」とありますが、バージョン範囲の見方は以下を参照ください。

[バージョンの範囲の参考サイト](https://prograshi.com/framework/nodejs/version-specification-in-package-json/)

キャレット（^）やチルダ（~）が付いている場合、基本的にはプロジェクト側のソースコードの変更を必要とするようなバージョン変更はされないので、依存関係を更新していっても問題ない、という認識で`npm install`が使われます（ただ、そうでないケースもあるので注意が必要です）

https://docs.npmjs.com/cli/v9/commands/npm-install


### 2. package-lock.jsonを元にパッケージをインストール
既存の`package-lock.json`を元にインストールする場合、以下のコマンドを実行します。


```sh
npm ci
```
- `node_modules`が存在する場合はいったん削除してから再インストールする
- `package.json`と`package-lock.json`の間に一致しない依存関係がある場合、エラーとなる（`npm install`はこの場合、`package-lock.json`を更新）
- `package-lock.json`のバージョンで固定してパッケージをインストールする
- `package.json`や`package-lock.json`ファイルは更新されない


自動的な依存関係の更新はせずに、`package-lock.json`でロックされたバージョンでインストールします。
プロジェクトの現状と全く同じバージョンで環境構築したい時に使用します。

https://docs.npmjs.com/cli/v9/commands/npm-ci

## ◆その他のよく使うnpmコマンド

ここからは、ただのメモに近いのですが…自分のためにも残しておきます。

### 1. パッケージのバージョン確認

インストール済みのパッケージのバージョン一覧を確認
```sh
npm list --depth=0    # ローカル
npm list --depth=0 -g # グローバル
```
- `npm list`のエイリアス→`npm ls`

`--depth=0`オプションをつけない場合、インストールしたパッケージが依存しているパッケージも出力される↓

```sh
npm list
```


リリースされているパッケージのバージョン一覧を取得するコマンド
```sh
npm info パッケージ名 versions
```

### 2. パッケージのアップデート

パッケージを指定
```sh
npm update パッケージ名
npm update パッケージ名@バージョン
```

全てのパッケージ
```sh
npm update    # ローカル
npm update -g # グローバル
```

- `package.json` に記載されているバージョンの範囲で最新のバージョンにアップデートする（世の中の最新のバージョンに更新されるわけではない）


###  3. パッケージのアンインストール

```sh
npm un パッケージ名    # ローカル
npm un -g パッケージ名 # グローバル
```

- `npm un`のエイリアス→`npm rm`
- パッケージ名をスペースで区切り、複数のパッケージを指定することもできる


## ◆最後に
記載内容にバラつきがあるかもしれません。
間違いがありましたらご指摘いただけましたら幸いです！

## ◆参考
https://docs.npmjs.com/cli/v9/commands

https://qiita.com/heppokofrontend/items/5c4cc738c5239f4afe02

https://qiita.com/mstssk/items/8759c71f328cab802670

https://morizyun.github.io/javascript/node-js-npm-library-node-fetch.html

https://qiita.com/fj_yohei/items/7ca887a45e0855917279