いまさら聞けない!npmのこれだけは知っておきたい基礎知識

2017/07/07

Michael Wanyoike

127

Articles in this issue reproduced from SitePoint
Copyright © 2017, All rights reserved. SitePoint Pty Ltd. www.sitepoint.com. Translation copyright © 2017, KADOKAWA ASCII Research Laboratories, Inc. Japanese syndication rights arranged with SitePoint Pty Ltd, Collingwood, Victoria,Australia through Tuttle-Mori Agency, Inc., Tokyo

いまや Webフロントエンド開発に欠かせなくなったNode.js。併せて使うことが多いnpmの使い方を基礎から学びましょう。

Node.jsは、サーバーでJavaScriptアプリケーションが書けます。V8 JavaScriptランタイムで動作し、C++で書かれているため高速です。当初、アプリケーションにサーバー環境を提供する目的でしたが、ローカル環境のタスク自動化ツールとしても利用されています。GruntGulpWebpackなどのNode.jsをベースにしたツールによる新たなエコシステムは進化を続け、フロントエンド開発の形を変えるまでに至りました。

Node.jsのツールやパッケージインストールしたり管理したりする方法を、Node.jsのパッケージマネージャーであるnpmが担っています。npmには必要なパッケージをインストールするほか、パッケージを扱うための便利なインターフェイスがあります。

本記事では、npmの基礎知識を紹介し、パッケージをローカルモード、グローバルモードでインストールする方法や、削除や更新の方法、特定のバージョンのパッケージをインストールする方法を説明します。package.jsonでプロジェクトの依存オブジェクトを管理する方法も解説します。

Node.jsのインストール

npmを使う前にNode.jsをシステムにインストールします。

Node.jsのダウンロードページで、Windows用インストーラー、Mac用インストーラー、コンパイル済みのLinux用バイナリ、ソースコードから必要なバージョンを選びます。ここで説明されているように、Linuxではパッケージマネージャーを使ってNode.jsのインストールができます。

本記事では、安定版のバージョン6.10.3を使います。執筆時のNode.jsの長期サポート(LTS:Long Term Support)版です。

ヒント:バージョンマネージャーを使ってNodeをインストールすると権限の問題を回避できます。

Node.jsのインストール先とバージョンを確認します。

$ which node
/usr/bin/node
$ node --version
v6.10.3

インストールが成功したか確認するために、Node.jsのREPLを試します。

$ node
> console.log('Node is running');
Node is running
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.exit  Exit the repl
.help  Show repl options
.load  Load JS from a file into the REPL session
.save  Save all evaluated commands in this REPL session to a file
> .exit

Node.jsがインストールできました。インストールに含まれているnpmも使えます。

$ which npm
/usr/bin/npm
$ npm --version
3.10.10

Node Packaged Modules(npm)

npmはローカルモード、グローバルモードでパッケージをインストールできます。ローカルモードではカレントワーキングディレクトリのnode_modulesフォルダーにパッケージをインストールします。フォルダーの所有者はカレントユーザーです。グローバルモードではrootが所有する{prefix}/lib/node_modules/にパッケージをインストールします( {prefix}は通常/usr//usr/local)。
パッケージをグローバルにインストールするにはsudoを使います。サードパーティ製依存オブジェクトの解決時にパーミッションエラーが出る可能性があり、セキュリティの懸念も残ります。対処方法を紹介します。

Parcel delivery company

パッケージ管理の時間

グローバルパッケージの場所を変更する

パッケージを管理します。

npm configの出力結果を見てください。

$ npm config list
; cli configs
user-agent = "npm/3.10.10 node/v6.10.3 linux x64"

; userconfig /home/sitepoint/.npmrc
prefix = "/home/sitepoint/.node_modules_global"

; node bin location = /usr/bin/nodejs
; cwd = /home/sitepoint
; HOME = /home/sitepoint
; "npm config ls -l" to show all defaults.

インストールの情報を確認できます。重要なのは、グローバルに設定されている場所の取得です。

$ npm config get prefix
/usr

プレフィックス(prefix)を変更して、グローバルパッケージをホームディレクトリにインストールします。ホームディレクトリに新たなディレクトリを作ります。

$ cd ~ && mkdir .node_modules_global
$ npm config set prefix=$HOME/.node_modules_global

簡単な設定の変更で、Node.jsのパッケージをグローバルにインストールする場所を変更できました。.npmrcファイルもホームディレクトリに作成されます。

$ npm config get prefix
/home/sitepoint/.node_modules_global
$ cat .npmrc
prefix=/home/sitepoint/.node_modules_global

rootの所有場所にnpmがインストールされたままです。グローバルパッケージの場所を変更したので、npmがインストール済みであることを逆手にとり、npmをもう一度、ユーザーが所有する新たな場所インストールします。最新バージョンのnpmがインストールされます。

$ npm install npm --global
└─┬ npm@5.0.2
  ├── abbrev@1.1.0
  ├── ansi-regex@2.1.1
....
├── wrappy@1.0.2
└── write-file-atomic@2.1.0

環境変数$PATH.node_modules_global/binを追加して、グローバルパッケージをコマンドラインから実行可能にします。.profile、.bash_profile、.bashrcに追加してターミナルを再起動してください。

export PATH="$HOME/.node_modules_global/bin:$PATH"

先に.node_modules_global/binが発見され、正しいバージョンのnpmが使われます。

$ which npm
/home/sitepoint/.node_modules_global/bin/npm
$ npm --version
5.0.2

グローバルモードでパッケージをインストールする

グローバルにインストールされたパッケージはnpmパッケージだけです。さらにUglifyJS(JavaScript圧縮ツール)をインストールします。--globalフラグを使います。省略形の-gでも大丈夫です。

$ npm install uglify-js --global
/home/sitepoint/.node_modules_global/bin/uglifyjs -> /home/sitepoint/.node_modules_global/lib/node_modules/uglify-js/bin/uglifyjs
+ uglify-js@3.0.15
added 4 packages in 5.836s

アウトプットを見ると、追加パッケージのUglifyJSの依存オブジェクトもインストールされたことが分かります。

グローバルパッケージを一覧表示する

npm listコマンドでインストールしたグローバルパッケージの一覧を表示できます。

$ npm list --global
home/sitepoint/.node_modules_global/lib
├─┬ npm@5.0.2
│ ├── abbrev@1.1.0
│ ├── ansi-regex@2.1.1
│ ├── ansicolors@0.3.2
│ ├── ansistyles@0.1.3
....................
└─┬ uglify-js@3.0.15
  ├─┬ commander@2.9.0
  │ └── graceful-readlink@1.0.1
  └── source-map@0.5.6

かなり冗長なアウトプットです。--depth=0オプションでアウトプットを変更します。

$ npm list -g --depth=0
/home/sitepoint/.node_modules_global/lib
├── npm@5.0.2
└── uglify-js@3.0.15

インストールしたパッケージとそのバージョン番号だけが表示され、すっきりしました。

グローバルにインストールしたパッケージはすべてコマンドラインから利用できます。Uglifyパッケージでexample.jsを圧縮しexample.min.jsを作るサンプルです。

$ uglifyjs example.js -o example.min.js

ローカルモードでパッケージをインストールする

パッケージをローカルにインストールするときは、package.jsonファイルを使います。

$ npm init
package name: (project)
version: (1.0.0)
description: Demo of package.json
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

Enterを押してデフォルトの設定を適用します。yesを押して確認します。プロジェクトのルートにpackage.jsonファイルが生成されます。

{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

ヒント:package.jsonファイルを素早く作るならnpm init --yを使います。

mainscripts以外のフィールドは見れば内容が分かります。mainフィールドはプログラムのプライマリエントリポイントで、scriptsフィールドはパッケージのライフサイクルで実行するスクリプトコマンドを指定できるフィールドです。ひとまずこのままで問題ありません。より詳しく学びたい場合はnpmのWebサイトにあるpackage.jsonのドキュメントnpmをビルドツールとして使うを読んでください。

Underscoreをインストールします。

$ npm install underscore
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN project@1.0.0 No description
npm WARN project@1.0.0 No repository field.

+ underscore@1.8.3
added 1 package in 0.344s

ロックファイルが生成されます。あとで説明します。

package.jsonを見ると、dependenciesフィールドに項目が追加されています。

{
  ...
  "dependencies": {
    "underscore": "^1.8.3"
  }
}

package.jsonによる依存オブジェクトの管理

Underscoreバージョン1.8.3をプロジェクトにインストールしました。バージョン番号の前にあるキャレット(^)は、package-lock.jsonファイルがないかぎり、インストールの際にメジャーバージョンが一致するものの中で最新のバージョンを取得することを意味します。ここでは、バージョン2.0.0未満のどれかになります。
依存オブジェクトのバージョニング方法(major.minor.patch)はセマンティックバージョニングとして知られています。詳しくは、セマンティックバージョニング:なぜ使う必要があるのかを参考にしてください。

Underscoreがdependenciesフィールドのプロパティとして保存されたことも重要です。最新バージョンのnpmから保存される仕様に変更しました。dependenciesフィールドはアプリケーションの実行に必要なUnderscoreなどのパッケージに使われます。
--save-devフラグを指定すればパッケージをdevDependencyとして保存できます。devDependenciesはテストの実行やコードのトランスパイルなど、開発目的のパッケージです。

package.jsonprivate: trueを追加すると、プライベートリポジトリを意図せずに公開する誤りを防ぎ、npm installの実行時に出力される警告を止めます。

package.jsonでプロジェクトの依存オブジェクトを明示する最大の理由はポータビリティです。誰かのコードを複製する場合、プロジェクトのルートでnpm iを実行すればnpmがアプリの実行に必要なパッケージをすべて取得します。詳細はあとで説明します。

Underscoreが稼働していることを確認します。プロジェクトのルートにファイル「test.js」を作成し、以下を追加します。

const _ = require('underscore');
console.log(_.range(5));

node test.jsでファイルを実行すると、画面に「0, 1, 2, 3, 4」と出力されます。

ローカルパッケージのアンインストール

npmはパッケージマネージャーなので、パッケージの削除もできます。Underscoreのパッケージに互換性の問題があると仮定し、パッケージを削除して古いバージョンをインストールします。

$ npm uninstall underscore
removed 2 packages in 0.107s
$ npm list
project@1.0.0 /home/sitepoint/project
└── (empty)

特定のバージョンのパッケージをインストールする

@マークをバージョン番号に付加すると、任意のバージョンのUnderscoreのパッケージをインストールできます。

$ npm install underscore@1.8.2
+ underscore@1.8.2
added 1 package in 1.574s

$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.8.2

パッケージの更新

Underscoreのパッケージに更新があるか確認します。

$ npm outdated
Package     Current  Wanted  Latest  Location
underscore    1.8.2   1.8.3   1.8.3  project

Currentはローカル環境にインストール済みのバージョンを示し、Latestはパッケージの最新バージョンを示します。Wantedは既存のコードを壊すことなくアップグレードできる最新バージョンです。

package-lock.jsonファイルは、プロジェクトをインストールしたすべてのマシンで依存オブジェクトを同じ状態に保つ目的でnpmバージョン5で導入されました。自動的に生成され、node_modulesフォルダーやpackage.jsonファイルを変更するnpmの操作で使えます。

package-lock.jsonファイルの機能を試します。node_modulesフォルダーを削除し、npm iを再度実行します。
最新バージョンのnpmでは、package-lock.jsonファイルに明示されているUnderscoreバージョン1.8.2をインストールします。古いバージョンのnpmでは、セマンティックバージョニングのルールでバージョン1.8.3をインストールします。以前は、パッケージのバージョン不一致が開発者にとって大きな悩みでした。npm-shrinkwrap.jsonファイルで対処していましたが、手作業で作成していました。

バグを修正した最新バージョンのUnderscoreでパッケージのバージョンに更新します。

$ npm update underscore
+ underscore@1.8.3
updated 1 package in 0.236s

$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.8.3

ヒント:作業前にpackage.jsonの依存オブジェクトにUnderscoreを指定します。npm updateを実行すれば古いモジュールをまとめて更新できます。

パッケージの検索

これまでmkdirコマンドを何度か使いましたが、同じ機能を持つNode.jsのパッケージがあるのかnpm searchで確認します。

$ npm search mkdir
NAME      | DESCRIPTION          | AUTHOR          | DATE       | VERSION
mkdir     | Directory crea…      | =joehewitt      | 2012-04-17 | 0.0.2
fs-extra  | fs-extra conta…      | =jprichardson…  | 2017-05-04 | 3.0.1
mkdirp    | Recursively mkdir,…  | =substack       | 2015-05-14 | 0.5.1
...

mkdirpがありました。インストールします。

$ npm install mkdirp
+ mkdirp@0.5.1
added 2 packages in 3.357s

mkdir.jsファイルを作って以下のコードをコピー&ペーストします。

const mkdirp = require('mkdirp');
mkdirp('foo', function (err) {
  if (err) console.error(err)
  else console.log('Directory created!')
});

ターミナルで実行します。

$ node mkdir.js
Directory created!

プロジェクトの依存オブジェクトを再インストールする

パッケージをもう1つインストールします。

$ npm install request
+ request@2.81.0
added 54 packages in 15.92s

package.jsonを確認します。

"dependencies": {
  "mkdirp": "^0.5.1",
  "request": "^2.81.0",
  "underscore": "^1.8.2"
},

依存オブジェクトの一覧が自動的に更新されました。古いバージョンのnpmは、npm install request --saveを実行して依存オブジェクトをpackage.jsonに保存する必要がありました。package.jsonに保存しないでパッケージをインストールしたい場合は、--no-saveを引数に与えます。

プロジェクトのソースコードを別のマシンに複製し、依存オブジェクトをインストールするなら、node_modulesフォルダーを削除して、npm installを実行します。

$ rm -R node-modules
$ npm list
project@1.0.0 /home/sitepoint/project
├── UNMET DEPENDENCY mkdirp@^0.5.1
├── UNMET DEPENDENCY request@^2.81.0
└── UNMET DEPENDENCY underscore@^1.8.2

npm ERR! missing: mkdirp@^0.5.1, required by project@1.0.0
npm ERR! missing: request@^2.81.0, required by project@1.0.0
npm ERR! missing: underscore@^1.8.2, required by project@1.0.0

$ npm install
added 57 packages in 1.595s

node_modulesフォルダーが再び生成されます。プロジェクトやソースリポジトリを依存オブジェクトで膨張させることなく、コードを簡単に共有できます。

キャッシュの管理

npmはパッケージをインストールするときにコピーを保持するため、同じパッケージが必要になったとき、ネットワークへのアクセスは不要で、ホームディレクトリの.npmディレクトリにコピーがキャッシュされます。

$ ls ~/.npm
anonymous-cli-metrics.json  _cacache  _locks  npm  registry.npmjs.org

時間が経つほどディレクトリーに古いパッケージがたまるので、クリーンアップをおすすめします。

$ npm cache clean

複数のNode.jsプロジェクトをシステムからクリーンアップしたいときは、すべてのnode_moduleフォルダーをワークスペースから一掃します。

find . -name "node_modules" -type d -exec rm -rf '{}' +

エイリアス

npmのコマンドを実行する方法は複数あります。一般的に使用されるnpmエイリアスをまとめました。

  • npm i <package>:パッケージをローカルにインストールする
  • npm i -g <package>:パッケージをグローバルにインストールする
  • npm un <package>:ローカルパッケージをアンインストールする
  • npm up:パッケージを更新する
  • npm t:テストを実行する
  • npm ls:インストールしたモジュールを一覧表示する
  • npm llまたはnpm la:モジュールを一覧表示するとともに追加のパッケージ情報を表示する

以下の方法で複数のパッケージを一度にインストールできます。

$ npm i express momemt lodash mongoose body-parser webpack

よく使われるnpmコマンドが知りたいなら、npm helpでコマンド一覧を確認できます。
さらに詳しく学ぶなら全部知ってる? npmを使いこなすために絶対知っておきたい10のことがオススメです。

バージョンマネージャー

複数のバージョンのNode.jsを同じマシンで管理するツールが用意されています。nnvm(Node Version Manager)などです。詳しくはnvmを使って複数のバージョンのNode.jsをインストールするで学べます。

最後に

このチュートリアルでは、npmを扱うための基礎知識を紹介しました。Node.jsをプロジェクトのダウンロードページからインストールする方法、sudoの使用を避けてグローバルパッケージの場所を変更する方法、ローカルモード、グローバルモードでパッケージをインストールする方法を説明しました。また、削除や更新の方法、特定のバージョンのパッケージをインストールする方法、プロジェクトの依存オブジェクトを管理する方法も説明しました。最近リリースされた機能について詳しく学びたい場合は、Githubにあるnpmのリリースについてのページを確認してください。

バージョン5の登場で、npmはフロントエンド開発の世界で大きな一歩を踏み出しました。npmのCOOによれば、npmのユーザーベースは変わりつつあり、npmを使う人の大半はNode.jsを書くためにnpmを使わないそうです。むしろ、フロントエンドでJavaScriptを統括するためのツール(本当に、npmを使えばなんでもインストールできます)になりつつあります。また、モダンJavaScriptを書くために必要不可欠な存在になっています。プロジェクトでnpmを使ってなければ、使い始めるのにちょうど良いタイミングだと思います。

本記事はGraham Coxが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。

本記事はnpmの最新状況と、バージョン5のリリースで導入された変更点を反映し2017年6月8日に更新しました。

(原文:A Beginner’s Guide to npm — the Node Package Manager

[翻訳:薮田佳佑/編集:Livit

Peter Dierx

クライアント向けにRuby on RailsのWebアプリケーションを作っているオランダのフリーランス開発者です。フロントエンドのJavaScriptフレームワークを触ることも好きで、新たなWebテクノロジー全般に興味があります。余暇には毎日サイクリングをしたりスカイダイビングに情熱を注いだりしています。

Copyright © 2017, Michael Wanyoike All Rights Reserved.

Michael Wanyoike

Michael Wanyoike

簡潔で読みやすいモジュール方式のコードを書きます。好きなことはワークフローの効率や生産性の向上に役立つ新たなテクノロジーを学ぶこと。最近はReactとJavaScriptにのめり込んでいます。

Loading...