はじめに
npm の公開について調べた際の記事の大半が古かったのと、バージョン管理等を忘れそうなため記録した。
公開に関係ないが調べてる際に面白かったものや、興味深かったものも同様に記録した。
情報を全く知らない人に教える気持ちで書いているのでくどい場所があるが無視して欲しい。
なお、 npm を持っていない人はおまけの公開のための環境構築を見て欲しい。
npm プロジェクトの作成
package.jsonの作成
以下のコマンドを入力し、質問に答えると package.json ができる。
npm init
すべての質問をエンターで進めると以下のように設定される。
name にはデフォルトで実行した場所のフォルダ名が入る。
その他の詳細はおまけのpackage.jsonの中身リストを見て欲しい。
{
"name": "test_npm_project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
デフォルトで LICENSE に入っている ISC とは Internet Systems Consortium が公開しているオープンソースライセンスのこと。
ざっくり言えば MIT ライセンスを短くしたもの。
シンプルさ故に採用されたとされている。1
パッケージ内容の作成
公開のテストのために以下のようなパッケージを作った。
npm run hello を使って、 "Hello World" を表示するだけの簡単なパッケージとなっている。
.
├── index.js
└── package.json
1 directory, 2 files
{
"name": "test_npm_project",
"version": "1.0.0",
"scripts": {
"hello": "node index.js"
}
}
console.log("Hello World");
実行例は以下の通りになる。
$ npm run hello
> hello-example@1.0.0 hello
> node index.js
Hello World
CLI パッケージを作るなら、おまけのおすすめライブラリで示すライブラリをお勧めする。
簡単に、文字に色をつけたりコマンドを作ったりできるようになる。
なお、以下のようにコマンド名で直接実行したい場合は package.json の bin フィールド を指定すれば良い。
$ hello-world
Hello World!
今回は、 version を 1.0.0 にしている。
しかし、開発段階にあるものは 0.1.0 から始めるべきであることを注意しよう。
npm パッケージの公開
npm パッケージを公開するためにはまずサインアップが必要である。
ローカル環境で npm にログイン
公式サイトで会員登録する。
アカウント作成後、ローカル環境から以下のコマンドでログインする。
npm login
なお、今どのアカウントでログインしているかは以下のコマンドで確認できる。
npm whoami
npm パッケージを公開
以下のコマンドで公開することができる。
npm publish
公開を確認する方法はおまけの公開後の確認方法にまとめているので興味があれば見て欲しい。
公開する前に、リポジトリを作成していない場合は git init を実行しておくとよい。
npm publish は Git の存在を必須とはしないが、パッケージの管理・バージョン履歴・GitHub 連携を行う際に必須となるため推奨される。
npm に公開したものは簡単に非公開にできない。
そのパッケージに入ってはいけないものが入ってないかをよく確認しよう。
確認すべきことはおまけの公開前に最低限確認しておきたいことにまとめてあるので興味があれば見て欲しい。
なお、公開を取り消すための条件は以下の通りとなっている。
- 公開から72時間以内である
または - npmのpublicであるパッケージが依存していない
- 直近1週間のダウンロード数が300未満
- メンテナーが一人だけである
公開した npm パッケージの管理
公開後の最も重要な作業はバージョンの更新を正しく行うことである。
バージョンの数え方はおまけの Version の数え方を見て欲しい。
バージョンを繰り上げるコマンドはおまけの npm version の使い方を見て欲しい。
なお、誤って公開してしまったバージョンや、重大なバグを含む古いバージョンは完全に削除できないため以下のコマンドを使い非推奨にしてユーザーに警告を出すようにする。
npm deprecate <package>@<version> "<message>"
また、依存パッケージの更新は定期的に行うべきである。
依存ライブラリが古くなると、セキュリティリスクが上がったり、 Node.js のバージョン非対応など等が起こり得る。
最低でも 数ヶ月に一度 は依存パッケージの更新をするべきである。
依存関係の更新は以下のコマンドですることができる。
npm update
おわりに
ふと思い出した際、大量のサイトをめぐるのも大変なため一つにまとめた。
おそらく表記ブレがあったり、読みづらい場所も多かったと思う。
間違えがあればコメントで教えていただけるとありがたい。
また、追加した方がいいものはコメントで教えてほしい。
ためになった、他の人の役に立ちそうだと思った方は、ハートをつけていただけると幸いです。
最後まで読んでいただきありがとうございました。
おまけ
今回の公開には直接関係ないものだが、間接的には関わってそうなものをまとめた。
基本的に本編のリンクから飛んで見ることを想定している。
もしあなたがそうではないなら読み飛ばした方がいい。
公開のための環境構築
npm コマンドを使うために Node.js が必要になる。
もし導入されていなかった場合、インストールしなければならない。
Node.js の存在確認
まず、 npm node の両方が入っていることを確認する。
node -v
npm -v
出力として以下のようにバージョンが表示されればインストールされている。
(出力例のバージョンでなくても問題ない。)
もしない場合はインストール必要がある。
$ node -v
v22.21.0
$ npm -v
10.9.4
Node.js の導入
Node.js は公式配布も、パッケージマネージャーでも npm を同梱している。
そのため、基本的に node だけが使用できるということはない。
今回は導入方法を複数個紹介する。
おすすめは Homebrew を使用する方法である。
Homebrew を使用
Homebrew を使えばインストールが一つのコマンドだけで完了する。
brew install node
インストール確認として以下のコマンドを実行すると良い。
node -v
npm -v
これでバージョンが表示されれば完了である。
公式サイトを使用
以下のサイトからインストーラをダウンロードする。
LST を選択し、インストローラをダウンロードする。
ダウンロードしたインストーラを実行し、Node.js をインストールする。
MacOS では .pkg 、Windows では .msi がインストーラとなる。
インストール確認として以下のコマンドを実行すると良い。
node -v
npm -v
これでバージョンが表示されれば完了である。
Node Version Manager を使用
複数バージョンを切り替えたい人向けのインストール方法である。
Node Version Manager の導入
まず、 Node Version Manager をインストールする。
最新バージョンは以下の公式リポジトリから確認してほしい。
執筆時点では v0.40.3 が最新だったため今回は curl / wget のどちらかを使用してインストールする。
以下のコマンドは v0.40.3 をインストールするコマンドである。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
Node Version Manager は現在 Homebrew 経由のインストールに対応していない。
そのため前述したような方法でインストールする必要がある。
Windows では Node Version Manager は動作しない。
(なお、 WSL(Windows Subsystem for Linux)を利用している場合は動作する。)
代わりに nvm-windows が提供されているため、Windows 環境の場合は以下のリポジトリからインストールする。
Node Version Manager を使った Node.js の導入
LTS 版を使用したい場合は、次のコマンドを実行する。
--latest-npm を付けると、最新版の npm も同時にインストールされる。
nvm install --lts --latest-npm
nvm alias default 'lts/*'
nvm alias default 'lts/*' は、最新の LTS バージョンをデフォルトに設定するためのコマンドである。
特定の Node.js バージョンを導入したい場合は次を実行する。
nvm install <version>
以下のコマンドを使用して現在のターミナルセッションで使用するバージョンを一時的に変えることができる。
nvm use <version>
package.jsonの中身リスト
自分で使いそうだと思ったものを列挙しておく。
なお、 npm pkg get <key> のコマンドで設定した内容を取り出せる。
$ npm pkg get version
"1.0.0"
name
{
"name": "my-new-package"
}
パッケージ名を示す。URLやコマンドラインの引数となる。
version
{
"version": "1.0.0"
}
現在のバージョンを示す。
バージョンの数え方はおまけの Version の数え方を見て欲しい。
また、このバージョンの上げ方はおまけの npm version の使い方を見て欲しい。
description
{
"description": "chocolate!"
}
なんのためのパッケージかを示すもの。 npm のパッケージ検索の時の指標となる説明を示す。
keyword
{
"keywords": ["chocolate", "cli", "clicker", ".w."]
}
npm のパッケージ検索の時の指標となるキーワードを示す。
license
{
"license": "ISC"
}
このパッケージのライセンスを示す。
homepage
{
"homepage": "https://your-package.org"
}
このパッケージのホームページ、ドキュメントのURLを示す。
bugs
{
"bugs": "https://github.com/user/repo/issues"
}
バグを発見した際に報告する場所を示す。
大半は GitHub の Issue ページが設定されている。
repository
{
"repository": { "type": "git", "url": "https://github.com/user/repo.git" }
}
このパッケージの実際のコードが置かれている場所を示す。
author
{
"author": {
"name": "yourname",
"email": "hoge@example.com",
"url": "http://your-website.com"
},
}
著者情報を示す。一人しか記入できない。
contributors
{
"contributors": [
{ "name": "A-Taro", "email": "A.Taro@example.com", "url": "http://a-taro.com" }
{ "name": "B-Taro", "email": "B.Taro@example.com", "url": "http://b-taro.com" }
]
}
開発に携わった人を示す。
main
{
"main": "index.js"
}
パッケージのメインエントリーの場所を示す。
bin
{
"bin": {
"myapp": "bin/cli.js"
}
}
実行可能ファイルの場所を示す。
ここで指定するファイルは、 #!/usr/bin/env nodeを最初に入れる。
これが無いと、インストール後にコマンドを実行しても正しく Node.js スクリプトとして扱われず、エラーになる場合がある
man
{
"man": "./man/doc.1"
}
プロジェクトに関するマニュアルページを示す。
directories
{
"directories": {
"lib": "src/lib",
"doc": "docs",
"man": "man"
}
}
ドキュメント、ライブラリ、マニュアルページなどのパッケージディレクトリの場所を示す。
scripts
{
"scripts": {
"start": "node app.js",
"test": "jest",
"lint": "eslint ."
}
}
npm 経由で実行できるコマンドを示す。よく使うものをここで設定するとよい。
基本的には npm run <command> で動くが、 start と test のみは run を省略できる。
config
{
"config": {
"port": "8080"
}
}
使用される構成オプションやパラメータなどを示す。
dependencies
{
"dependencies": {
"chocolate": "^1.0.0"
}
}
依存関係を示す。
依存関係のバージョンの書き方に関してはおまけの依存関係を見て欲しい。
devDependencies
{
"devDependencies": {
"chocolate": "^1.0.0"
}
}
インストールはされないが、開発する際に必要なものを示す。
peerDependencies
{
"peerDependencies": {
"chocolate": "^1.0.0"
}
}
他のパッケージとの互換性を示す。
optionalDependencies
{
"optionalDependencies": {
"chocolate": "^1.0.0"
}
}
パッケージと一緒に使うこともできるが必要ではないものを示す。
bundledDependencies
{
"bundledDependencies": ["chocolate"]
}
パッケージ公開時に 依存パッケージを内部に同梱するものを示す。
resolutions
{
"resolutions": {
"chocolate": "1.0.0"
}
}
依存関係ツリー内で、特定パッケージの バージョンを強制的に固定する ことを示す。(Yarn で主に使用)
system
{
"system": "linux"
}
特的のシステム環境向けであることを示す。
一般的には使われない。
engines
{
"engines": {
"node": ">=18"
}
}
対応する Node.js や npm のバージョン要件を示す。
os
{
"os": ["darwin", "linux"]
}
パッケージがどの OS で動作するかを示す。
{
"os": ["!win32"]
}
なお、 ! でブロックする OS を示せる。
cpu
{
"cpu": ["x64", "arm64"]
}
対応するCPUアーキテクチャを示す。
private
{
"private": true
}
パッケージをnpmへ公開できないようにする設定を示す。
publishConfig
{
"publishConfig": {
"access": "public"
}
}
npm publish時にに使われる公開設定を示す。
たとえば、スコープ付きパッケージ(@user/package)はデフォルトで private になる場合があるため、
access: "public" を指定して明示的に public として公開する、といった用途で使う。
files
{
"files": ["dist", "bin"]
}
npm publish したときに、どのファイル / ディレクトリを含めるかを示す。
Versionとは
ソフトウェアや製品の改訂版を識別するための番号や表記のことである。
Version の数え方
一般的なものと一緒で npm も X.Y.Z-N というバージョンの形をする。
X、Y、Z、Nが何かを簡単に説明すると以下のようになる。
- X - メジャーバージョン
- 大規模な変更の際に繰り上がる
- 互換性が途切れる際に上がる
- Y - マイナーバージョン
- 小規模な変更の際に繰り上がる
- 互換性は途切れなく、何かしらの機能を追加した際に繰り上がる
- Z - パッチバージョン
- バグの修正の際に繰り上がる
- 互換性は途切れなく、何かしらの機能の追加でもない、バグ修正の修正した際に繰り上がる
- N - プレリリースバージョン(プレリリース識別子)
- 正式版になる前のテスト段階のバージョンを表す
- 互換性は安定しておらず、あくまで開発者・テスター向け
メジャーバージョンが0の時は、ソフトウェアの最初の開発段階を示している。
なお、開発段階にも2種類ありアルファ版とベータ版というものがある。
アルファ版は開発初期段階で、内部のテスターや開発者向けに、主要なバグや性能の問題点を発見する目的で用いられ、
ベータ版は実際のユーザーに試してもらい、様々な環境での動作確認や使い勝手に関するフィードバックを収集する目的で用いられる。
なお、リリース候補版のことをガンマ版と呼ぶこともあるらしい。2
npm version の使い方
npm version は以下の9つの引数を取る。
場合によって使い分けよう。
もし、メジャーバージョン、マイナーバージョンなどがわからない場合はおまけの Version の数え方を見て欲しい。
<newversion>
問答無用でバージョンをあげるコマンド。
npm version 999.999.999
とすれば、たとえバージョンが今 0.1.0 だろうとも 999.999.999 になる。
major
メジャーバージョンをあげるコマンド。
minor
マイナーバージョンをあげるコマンド。
patch
パッチバージョンをあげるコマンド。
premajor
後ろに -0 をつけてメジャーバージョンをあげるコマンド。
今が 1.0.0 でこのコマンドを使えば、 2.0.0-0 になる。
preminor
後ろに -0 をつけてマイナーバージョンをあげるコマンド。
今が 1.0.0 でこのコマンドを使えば、 1.1.0-0 になる。
prepatch
後ろに -0 をつけてパッチバージョンをあげるコマンド。
今が 1.0.0 でこのコマンドを使えば、 1.0.1-0 になる。
prerelease
後ろの -0 の数字を繰り上げるコマンド。
今が 1.0.0-0 でこのコマンドを使えば、 1.0.0-1 になる。
後ろにプレリリースバージョンがなければパッチバージョンをあげて、 -0 をつける。
そのため prepatch と役割が異なるので気をつけよう。
$ npm pkg get version
"1.0.0"
$ npm version prerelease
v1.0.1-0
from-git
git上で設定された最新のタグを読み、そのタグのバージョン番号を設定するコマンド。
依存関係
依存関係とは、あるパッケージを前提に成り立っているもののことを指す。
依存関係のバージョン
dependencies で示される依存関係にはバージョンが記載されているが、書き方によってインストールされるものが変化する。
バージョンの書き方には大きく分けて以下の4種類が存在する。
もし、メジャーバージョン、マイナーバージョンなどがわからない場合はおまけの Version の数え方を見て欲しい。
^(キャレット)
"chocolate": "^1.0.0"
メジャーバージョン以外の更新ならしてよいことを示す。
つまり互換性が保たれている範囲で自動更新をする。
例:
^1.0.0 の場合、以下がインストールされうる:
- 1.1.0
- 1.2.0
- 1.9.9
なお次のものはメジャーバージョンが違うため更新されない。
- 2.0.0
^ がデフォルトになっているのは、基本的に「互換性が維持される範囲なら自動更新したい」ケースが多いためである。
~(チルダ)
"chocolate": "~1.0.0"
メジャーバージョン、マイナーバージョン以外の更新ならしてよいことを示す。
つまりパッチバージョンだけ自動更新する。
例:
~1.0.0 の場合、以下がインストールされうる:
- 1.0.0
- 1.0.1
- 1.0.99
なお次のものはメジャーバージョンまたはマイナーバージョンが違うため更新されない。
- 1.1.0
- 2.0.0
完全固定(ピン留め)
"chocolate": "1.0.0"
バージョンが完全に固定されていることを示す。
自動更新しないため、バージョン起因の不具合を避けたい時に使われる。
意図せぬ依存パッケージの古さが残ることもあるため注意。
*(ワイルドカード)
"chocolate": "*"
どのバージョンでもOKという意味。
開発中や内部ツールでしかほぼ使われない。
公開パッケージでは推奨されない。
node_modules の構造パターン
node_modules とは npm でインストールしたパッケージを格納しているフォルダのことを指す。
最近の npm では、可能な限り依存パッケージを node_modules の直下にまとめる方式、いわゆる Flat インストールを採用している。
├── node_modules
│ ├── A
│ ├── B
│ ├── C
│ ...
...
v2以前の古い npm では、依存パッケージごとに自分の node_modules を持つというネスト構造が普通だった。
この方法は同じ依存パッケージが複数場所に重複してインストールしてしまい、ストレージを圧迫したりパス長制限に引っかかるなどの問題を引き起こしていた。
そこで、 npm v3 でこの問題に対応し、Flat に近づける方式へと変更された。3
├── node_moduels
│ ├── A
│ │ └── node_moduels
│ │ ├── AA
│ │ ├── AB
│ │ ├── AC
│ │ ...
│ ├── B
│ │ └── node_moduels
│ │ ├── BA
│ │ ├── BB
│ │ ├── BC
│ │ ...
│ ├── C
│ │ └── node_moduels
│ │ ├── CA
│ │ ├── CB
│ │ ├── CC
│ │ ...
... ...
なお、 Flat に近づける方式へ変更はされたが、依存関係同士の要求するバージョンに競合がある場合はネストされる。
要するに、現在の npm の実装は、「できるだけフラット」だが、「バージョン競合がある場合だけネスト」というハイブリッド方式となっている。
この方式により、効率と互換性のバランスを取っている。
下の例は、 C のみが古いバージョンの D に依存している場合の node_modules 構造である。
共有できるバージョンの D はルート直下に置かれるが、C が別バージョンの D を要求している場合、その分だけ C/node_modules/D としてネストされている。
├── node_modules
│ ├── A
│ ├── B
│ ├── C
│ │ └── node_modules
│ │ └── D@v1.0.0
│ ├── D@v2.0.0
│ ...
...
おすすめライブラリ
npm は以下のコマンドを使えば簡単にライブラリを追加することができる。
その際に自動で package.json も更新される。
$ npm install <package-spec>
以下におすすめなライブラリを示す。
chalk
文字に色をつけるライブラリ。
インストール
npm install chalk
使用例
import chalk from 'chalk';
console.log(chalk.blue('Hello World'));
yargs
コマンドライン引数をパースするライブラリ。
インストール
npm install yargs
使用例
#!/usr/bin/env node
const yargs = require('yargs');
const slicedArgs = process.argv.slice(2);
const argv = yargs(slicedArgs)
.option('chocolate', {
alias: 'c',
description: 'number of chocolates',
type: 'number'
})
.option('chocolate-type', {
alias: 'ct',
description: 'type of chocolates',
type: 'array',
default: ['dark', 'white']
})
.help().argv;
console.log(argv.c);
console.log(argv.ct);
出力例
$ node index.js --help
オプション:
--version バージョンを表示 [真偽]
-c, --chocolate number of chocolates [数値]
--chocolate-type, --ct type of chocolates
[配列] [デフォルト: ["dark","white"]]
--help ヘルプを表示 [真偽]
$ node index.js --c 1
1
[ 'dark', 'white' ]
公開後の確認方法
npm publish が正しく完了したかどうか、また公開された内容を確認するには以下のコマンドが便利である。
このコマンドを実行しても 404 Not Found が帰ってきた場合、公開がうまくいっていない。
npm info <package-name>
得られる主な情報は以下の通りとなる。
- 最新バージョン (latest)
- パッケージの説明 (description)
- 公開されているバージョン一覧
- 依存関係 (dependencies)
- メンテナー情報
- dist-tags
なお、特定のフィールドだけを取り出したい場合は以下のコマンドが使える。
npm view <package-name> <field>
CLI の作り方
package.json は以下の通りにする。
bin フィールドで指定しているものがコマンドとなる。
{
"name": "hello-world-cli",
"version": "1.0.0",
"type": "module",
"bin": {
"hello-world": "./index.js"
}
}
あとは index.js を実行可能にしておく。
#!/usr/bin/env node
console.log("Hello World!");
これで次のコマンドでインストールすれば CLI として動作する。
npm install -g .
実行例は以下の通りになる。
$ hello-world
Hello World!
公開前に最低限確認しておきたいこと
npm publish を実行する前に、次の点だけは確認しておくと安全である。
-
npm packを実行して、公開される内容をローカルで確認する -
.npmignoreまたはpackage.jsonのfilesで不要なファイルが入っていないか確認する -
.envや秘密鍵などが含まれていないかを確認する - バージョン番号を上げているか確認する(同じバージョンは上書きできない)
.npmignore とは
.npmignore は npm に公開する際の含めないファイルやディレクトリを指定するためのファイルである。
役割としては .gitignore に似ているが、 npm の公開内容にのみ影響する点が大きく違う。
もし .npmignore を用意しなかった場合、 npm は package.json の files フィールドか、 npm のデフォルト除外ルール等に従って公開対象を判断する。4
しかし、意図しないファイルが含まれるかもしれないため、公開パッケージを安全に管理したい場合は .npmignore で明示的に除外するのが望ましい。
npm のデフォルト除外ルール
.npmignore がない場合でも、 npm publish ではあらかじめ除外されるファイル / フォルダが存在する。
例えば以下のようなものが、明示的に指定しなくても除外される。
-
.*.swp(エディタの一時ファイル) -
._*(一部隠しファイル) .DS_Store.git-
.gitignore/.npmignore(ignore 定義ファイル自身) -
.hg/.svn(他の SCM 管理フォルダ) .npmrcnpm-debug.log-
CVS/config.gypi/.wafpickle-*/.lock-wscript(ビルドや古い管理関連ファイル)
.npmignore で除外ができないファイル
次のようなファイルは .npmignore に書いても無視されず、必ず公開パッケージに含まれる。
これらはパッケージ利用側に必須とみなされているためで、 .npmignore で除外したい場合でも効果がない。
package.json-
README(拡張子違いでも対象) -
LICENSE/LICENCE
.npmignore と .gitignore とデフォルト除外の関係
npm publish の対象ファイルは次の優先順位で決まる。
-
package.jsonのfiles フィールド .npmignore-
.gitignore(.npmignoreがない場合のみ) -
npmのデフォルトの除外ルール
-
https://corner.buka.sh/understanding-the-isc-license-in-npm-projects-a-developers-guide/ ↩
-
https://atmarkit.itmedia.co.jp/ait/articles/1003/26/news106.html ↩
-
https://npm.github.io/how-npm-works-docs/npm3/how-npm3-works.html ↩
-
https://docs.npmjs.com/cli/v11/using-npm/developers#keeping-files-out-of-your-package ↩
