npmでパッケージを公開してみた手順の記録

# 概要

npmで、初めてパッケージ（ライブラリ）を公開してみるまでの手順の記録＠Windows環境。

## 大雑把な手順

npmで自作のライブラリをパッケージとして公開するまでの手順は以下。トラブらなければ１ｈ未満で完了できると思う（当方は、トラブッたので２ｈかかった）。

1. npmアカウントを作成する
2. ローカルのnpmコマンドでアカウントにログイン
3. 公開用のファイルを準備する（package.jsonとかREADME.mdとか）
4. npmに公開する（これ自体は、コマンド１つ叩くのみ）

前半は「準備すべきこと」を記載してるので、「で、どういう手順で公開するの？」に急ぎたい方は[後半](#%E5%85%AC%E9%96%8B%E3%81%BE%E3%81%A7%E3%81%AE%E6%93%8D%E4%BD%9C%E6%89%8B%E9%A0%86)へ。

## スタートとゴール地点

スタート地点は以下。

 * 公開するライブラリは作成済み
    * ※β版でもOKとする
　　* ※npmコマンド自体（npm install等）は既に利用している、とする
 * テストも作成済みで、passする
    * ※pendingを含む
 * GitHubアカウントは持っている
    * ※必須ではないが、あることを前提に以下の手順は成り立っているので、必要に応じて読み替え。→LICENSE記述等
    * ※リポジトリは、npm用に新規作成する前提。既存を使う場合は適当に読み替え

「作成済み」とは、以下のようなファイル構成を想定している。

```
src/*
test/*
index.js
package.json
```

ゴール地点は以下。

登録したパッケージ（例：HOGE、とする）を、npmでインストールできること。

```sh
npm install --save HOGE
```


実際に当方が作成したnpmパッケージ（のGitHubリポジトリ）は以下。
https://github.com/hoshimado/hook-test-helper

※なお、上記は随時更新されていく。この記事を書いた時点でのbranchはこちら。
https://github.com/hoshimado/hook-test-helper/tree/v0.0.2-gather-sample-and-remove-from-npm


誰かの参考になれば幸い。




# npmでのパッケージ公開時に作成すべきもの（準備）

「作成したライブラリをnpmでパッケージとして公開しよう！」とする場合に、必要なのは以下。

 * npmアカウント
 * README.md
 * index.js
 * package.json
 * Githubアカウント（必須ではないが在った方が良い）
 * .gitignoreファイル（下記の.npmignoreファイルといづれかもしくは両方が必要）
 * .npmignoreファイル（必須ではないが在った方が良い）
 * ライセンスファイル（必須ではないが在ったほうが良い。GitHubが作ってくれるテンプレート利用が楽）


## npmアカウント

npmにライブラリを登録するために必要。いかの４つを入力してアカウント作成する。

 * Full Name (後で変更可能)
 * Public Email （確認メールが来る。そこでOK応答して完了。後で変更可能）
 * Username （作成者としての識別用。変更可能かは未確認）
 * Password （もちろん後で変更可能）

なお、後からお好みで以下も紐づけ可能のようだ。

 * GitHub UserName
 * Twitter Username

登録後に変更可能な設定項目は、公式ドキュメントの「Setting up Your Profile from the Web」を参照。
https://docs.npmjs.com/getting-started/installing-node#after-you-set-up-your-login-account


## README.mdファイル

パッケージの紹介文。
例えばこんな感じで、npmの公開ページで表示される。
https://www.npmjs.com/package/hook-test-helper

GitHubのリポジトリで表示される「リポジトリの説明文」とほぼ同じ位置づけ。記法も同じ（Markdown）。Github側の表示例はこんな感じ。
https://github.com/hoshimado/hook-test-helper

最低限書いておけばよい内容は、以下だろうか。

 * タイトル
   * 概要の説明
 * インストール方法
 * 使い方

他のパッケージでのGithubのREADME.mdの例を参考に書く。
私の場合は、promise-test-helper あたりを参照した。
https://github.com/azu/promise-test-helper

記法はマークダウン。Visual Studio Code のプレビュー画面を見ながら書くのがお勧め。後で述べる「バッチ」もそのままプレビューで表示してくれる。
![スクリーンショット 2018-07-13 06.32.25.png](https://qiita-image-store.s3.amazonaws.com/0/125588/27119881-403a-9fa6-22f9-83d11f1cb530.png)



## index.jsファイル

ライブラリとしてのエントリポイント。
他のファイルにすることもできるが、デフォルトだとこれに成る。

ライブラリとして提供する関数が `method1()` だとすると、
以下のように書いておけばよい。通常の外部公開と同じ。

```javascript:index.js
exports.method1 = method1;
```

こう書いておくと、ライブラリのパッケージ名がhogeだとすれば、以下のように参照できる。

```sh
npm install hoge
```

```javascript:main.js
var hoge = require("hoge");
var method1 = hoge.method1;
```

## package.jsonファイル

公開するライブラリが必要とする別のライブラリなど、を記載しておく。通常と同様に 'npm init' で作成すればよい。気を付けるべきは以下の項目かな。

```json:package.json
{
  "name": "ライブラリの名称",
  "version": "バージョン。公開毎に変更必要。β版なら「0.0.1」とかにしておけばよい",
  "description": "ライブラリの説明を簡単に記載",
  "main": "エントリポイントのファイル。通常は「index.js」としておく。",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "cross-env NODE_ENV=development node_modules/.bin/mocha"
  },
  "author": "作者名",
  "license": "MIT",
  "devDependencies": {
    "chai": "^4.1.2",
    "cross-env": "^5.2.0",
    "mocha": "^5.2.0",
    "promise-test-helper": "^0.2.1",
    "sinon": "^6.1.2"
  }
}
```

いくつか補足。

* gitの項目
  * githubのリポジトリ上で「npm init」する際にデフォルト値として入れてくれるので、そのままEnterが楽。
* scriptのtest項目
  * テストの実行パスをローカルパスで書いておく。当方の場合は、環境変数を指定して実行したかったので、cross-env利用しているが、不要なら単純に（Mochaでテストするなら）「node_modules/.bin/mocha」でOK。
* author項目
  * 入力を忘れずにしよう。

* 利用する別のライブラリ（依存するライブラリ） 
  * `npm init` 後に `npm install --save hogehoge` や `install install --save-dev fugafuga` したものがdependencies, devDependenciesの項目に登録されるので、それらが在ればOK。


## GitHub のアカウント

npmでパッケージ公開する際に **必須ではない** ようだが、在った方が何かと都合が良い。その理由は以下。

* リポジトリ作成時に、node.js向けの「.gitignore」ファイルを自動生成できる。
* リポジトリ作成時に、ライセンスファイルを（MITなどの汎用の物なら）自動生成できる。

※GitHubでリポジトリ作成時に、.gitignoreファイルやライセンスファイルをいい感じに自動生成する方法はこちらで書いたので興味あれば参照↓。
[Node.jsのコードを新規生成するときの前準備。GitHub利用前提のメモ。](https://qiita.com/hoshimado/items/f8b14373bf56c29cbdcf)

## .gitignoreファイル

Gitに **公開しないファイル** （公開したくないファイル）を定義するファイル。ローカルファイルシステムのサムネイル一時ファイルとか、パスワード書いたファイルと**公開されるとまずいファイル**を管理するうえで、ほぼ必須。

で、npmのパッケージ内に**含めたくないファイル**の定義は、後述の「.npmignoreファイル」が無い場合には、この「.gitignoreファイル」に記載されたルールに従う。

大抵の場合、「Gitに公開したくないファイル」**⊂**「npmに公開したくないファイル」になるので、少なくともこの gitignore ファイルを準備しておくことで、「意図しないファイルが公開されてしまった！」を防げる確率はあがる。GitHubでのリポジトリ生成時に自動生成してくれるし。

## .npmignoreファイル

npmに**公開したくないファイル**を定義する。
記法は、「.gitignoreファイル」と同じ。なお、**「.npmignoreファイル」がある場合は「.npmignoreファイル」に記載されたルールのみが有効**になり、「.gitignoreファイル」に記載されたルールはnpm側には適用されないので注意。

## ライセンスファイル

利用時のライセンスについて記載したファイル。私の場合は、Githubのリポジトリ側を「MIT」にしたので、npm側も同様にMITライセンスにしている。GitHubのリポジトリ作成時に自動生成したMITライセンスファイルをそのまま利用。



# 公開までの操作手順

公開の前準備、でそこそこ時間を食われた。
途中、npm環境のトラブルも入ったので２ｈくらい？だろうか。
そういうのが無ければ１ｈくらいで出来るかもしれない。

## npmアカウントを作成する

npmの公式ページにアクセスする。
http://www.npmjs.com

![スクリーンショット 2018-07-07 11.11.32.png](https://qiita-image-store.s3.amazonaws.com/0/125588/a03e8868-1b84-b16a-7283-76c9c120fd31.png)


公式のドキュメントの以下のページ「Getting started＞03 - How to set up a new npm account & install npm」を参照して npm アカウントを作成。入力したメールアドレスに確認メールが飛んでくるので、それに応答すれば登録完了。
https://docs.npmjs.com/getting-started/installing-node#Related-CLI-Commands

（ところで、「Create an account. Go to http://www.npmjs.com and click 'log in'.」と記載があるが、これは「'sign up'」の誤記が気がする。login画面から「Create Account」リンク先へ移動する必要があって、移動先はsignup画面だから。）

アカウント作成に成功して、npmの管理Webページにログインすると、こんな感じになる。

![スクリーンショット 2018-07-07 11.18.47.png](https://qiita-image-store.s3.amazonaws.com/0/125588/28ae168a-7589-2b00-15c5-7e22261b819d.png)


### 余談：login時に熊が目隠しするの、芸が細かいｗ

login 画面（作成済みアカウントでのログイン画面）で、パスワードにキー入力フォーカスを当てると熊が目隠しする。芸が細かいｗ

![スクリーンショット 2018-07-07 11.11.49.png](https://qiita-image-store.s3.amazonaws.com/0/125588/7da0b036-0a47-2494-f6c9-df975cbb78ba.png)

![スクリーンショット 2018-07-07 11.12.10.png](https://qiita-image-store.s3.amazonaws.com/0/125588/492804eb-fbae-e05c-f115-dd6495528e12.png)


## ローカルのnpmコマンドでアカウントにログイン

Webページ上（npm公式＞signup）でアカウントを作成したら、続いてローカル環境のnpmコマンドから作成したアカウントにログインする。

ログイン自体は簡単で、以下のコマンドを実行すればよい。

```sh
npm login
```

ユーザー名とパスワードとメールアドレスを聞かれるので、アカウント作成時に入力した値を入れる。

https://docs.npmjs.com/getting-started/installing-node#login-to-npm-from-a-terminal
> Login to npm from a terminal
> To test your new account, type:
> 
> npm login

ログインした状態で、「npm publish」を実行すると、それだけで全世界に対してnpmパッケージを公開できる。が、その前に「公開しないファイル」設定などに漏れが無いか確認していく。


### 余談：コマンドラインだけでもnpmアカウント作成できる？

Webページを経ることなくnpmコマンドだけでもアカウント作成は出来るようだ。しかし、公式ドキュメントに以下のように「1.Webページでアカウント作成、3.ローカルにnpmインストール、3.ローカルのnpmコマンドでログイン」と書いてあるので、初心者向けにはこの手順が推奨なのだろう。
https://docs.npmjs.com/getting-started/installing-node

> Create an account from npmjs.com.
> Install npm from a terminal console.
> Login to the terminal with your new username.


### 余談：公式手順に従ってnpm最新化したらハマった件（動かなくなった）

「getting-started ＞ Install npm from a terminal console.」に以下の記載が在ったので、うっかり「この機会に最新版へアップデートしておくか」と軽く考えて実行したらハマった件。具体的には **npmコマンドがエラー吐いて動かなくなった。アップデートもダウングレードも何もできない**。。。orz

https://docs.npmjs.com/getting-started/installing-node#3-update-npm
> 3. Update npm
> When you install node.js, npm is automatically installed. 
> However, npm gets updated more frequently than Node.js, so be sure that you have the latest version.
> 
> To test, run npm -v.
> 
> To be sure that this matches the latest version, scroll to the bottom of this page. 
> If the version you see does not match the latest version, run:
> 
> npm install npm@latest -g.


原因としては、node.js と npm のバージョン不整合。アップデート前は「npm@2.15.9」/「node@4.5.0」だったんだが、最新版「npm@6.1.0」にしたところ、このnpmは「node@4.5.0」環境では動かない版だった。「letは知らない子です」とかエラーメッセージが出た（エラー内容は確か SyntaxError: Unexpected identifier、、、だった気がする。あー、そういえば最近のnodeはletサポートして、こっちが推奨なんだっけー）。

たぶんこれ、私のnode側の環境が古くてletサポートしてないからかなー、ってことで、この際なので、Node側を最新化してみた。面倒だったので、Node.jsの最新版（node@8.11.3）を公式から落としてきてインストール。よーし、npmコマンドは動いた♪
https://nodejs.org/ja/

・・・と思ったら、今度は作成済みの**既存のソースコードが動かなくなった、という二段構えの罠**。あー、そういえば、パッケージによっては実装が Node.js のバージョン依存のヤツもあるんだっけ、、、ってことで、そのソースコードで利用しているnpmパッケージを入れなおすことにした。具体的には以下を実施。

```sh
rmdir /S /Q node_modules
npm install
```

node_modulesフォルダを削除して、npmパッケージを（package.jsonに従って）インストールし直した。これで無事に動くようになった♪



## 公開用のファイルを準備する（package.jsonとかREADME.mdとか）

ライブラリ公開のための体裁を整える。
どんなファイルを準備すべきかは、公式ドキュメントの以下のページを参照。

> 11 - How to create Node.js modules
https://docs.npmjs.com/getting-started/creating-node-modules

> 12 - How to publish & update a package
https://docs.npmjs.com/getting-started/publishing-npm-packages

具体的には、「12.＞Review the Package Directory」に記載がある「.gitignore or .npmignore file.」と「package.json File」、「Include Documentation (readme.md)」を準備する。
https://docs.npmjs.com/getting-started/publishing-npm-packages#review-the-package-directory

 * README.md
 * index.js
 * package.json
 * .gitignore
 * .npmignore

上記のファイルを用意したら、以下を確認するのが良い。

### 依存関係の記述の検証

node_modules フォルダを削除した後に、`npm install` で依存パッケージを再インストール。その状態で、ライブラリが期待した動作をするか再確認 ⇒ `npm test` でテストが通るか確認すればOK。

### 公開されるファイルを検証

```sh
npm pack
```

上記のコマンドで、「npm publish」コマンドを実行したときに、どのようなファイルが公開されるか？を確認できる。
`<name>-<version>.tgz` ファイルが生成されるので、これを展開する。「展開したファイル群＝公開されるファイル群」に成るので、
意図しないファイルが含まれていないかを確認する。

https://docs.npmjs.com/cli/pack
> Create a tarball from a package

**意図しないファイルが含まれていた**場合は、.npmignore ファイルを修正する。なお、再度 `npm pack` を実行する前に、
上記で生成した tar ファイルは削除しておくこと（.npmignore ファイルで tar を「対象外」指定していない場合、既存のtarファイルまで再パックされてしまうので）。


## npmに公開する（これ自体は直ぐ終わる！）

公開用のファイルの検証まで終えたら、後は「公開」するのみ。
「npm login」済みの環境で、おもむろに以下を打ち込む。

```sh 
npm publish
```
![スクリーンショット 2018-07-08 14.13.36.png](https://qiita-image-store.s3.amazonaws.com/0/125588/6a8fb847-a4e7-ede1-c1ca-f9756dae6c5c.png)


これで、npmへの自作ライブラリの公開は完了。
任意のフォルダ上のコマンドラインから、`npm install 「公開したパッケージ名」` を打ち込んで**ライブラリがインストールされる様**をニマニマしながら確認しましょうー（これで公開が正しく行われたかの検証も終了ー）。

お疲れ様でした！

## 余談：logoutしておいた方が良い

`npm publish`した後は、毎回「npm logout」しておいた方が良さ気。npm loginしたままbranchを切り替えたら、publish で以下のエラーになったので。

```
npm WARN notice Due to a recent security incident, all user tokens have been invalidated.
```

npmでパッケージ公開するときは loginからlogoutまでで一セットにしておいた方が安心感があるんじゃなかろうか？

```sh
npm login
npm pack
npm publish
npm logout
```


# その他：公開済み npm パッケージのアップデート方法

## 公式の推奨する方法（バージョンは自動更新）

公開済みのnpmパッケージを公開するには、以下のようにする。

```sh
npm version patch
npm publish
```

これは「バージョンの数値自体は、気にしない。その修正が パッチなのかマイナーアップなのか、それともメジャーバージョンアップなのか？にだけフォーカスせよ」、、ってことみたい。バージョンの数値自体は、npm version コマンドが内部で**自動的に変更**する。

「`npm version patch`」コマンドで以下が実行される。

1. package.json ファイルの `"version" : "m.n.p"` の部分が `"version" : "m.n.p+1"` にインクリメントされる。
2. gitへのステージングとコミットが成される。（プッシュはされない）

続く `npm publish` コマンドで以下が実行される。

3. npmにパッケージが公開される。

https://docs.npmjs.com/getting-started/publishing-npm-packages#how-to-update-the-version-number
> How to Update the Version Number
> 
> When you make changes, you can update the package using
> 
> npm version <update_type>
> 
> where <update_type> is one of the semantic versioning release types, patch, minor, or major.
> 
> This command will change the version number in package.json.
> 
> Note: this will also add a tag with the updated release number to your git repository if you have linked one to your npm account.

＜update_type＞のところには「patch, minor, or major」のいづれかを指定する（上記では patch を指定した）。
それぞれ、以下の用途で使うのが推奨されている。
https://docs.npmjs.com/getting-started/semantic-versioning

* pacth は「バグ修正、その他の小さな修正」
* minor は「新機能の追加など。ただし、既存バージョンとの互換を保つ」
* major は「既存バージョンとの互換性を破壊するような、変更」

それぞれの実際の動作としては、package.json の version キーの以下の部分を自動でインクリメントする。

* patch は 0.0.x 
* minor は 0.x.0
* major は x.0.0

例えば、package.json が「 `"version" : "0.0.2"` 」の状態に対して `npm version minor` すると、「 `"version" : "0.1.0"` 」へ変化する。
また、npm側でgitアカウントへの紐付けをしていると、「npm version」のタイミングでタグも切ってくれるらしい（実行は未確認）。
なお、patch、minor、

※`npm version` はgit操作を内部に含む仕様から、実行前にそれまでの変更分のGitへのコミットが完了してないと、エラーに成る様子。

Gitコミットも含めると、以下のような流れになるだろうか？

1. 更新版のモジュールを、master ブランチへPull Requestして、Margeする。
2. master ブランチをチェックアウトしてくる（masterへ切り替える）。
3. `npm login` でnpmアカウントに入る。
4. `npm pack` で、不要なファイルが公開されないことを確認する。
5. `npm version` でバージョンを更新する（patch / minor / major）。
6. `npm publish` でモジュールを公開する。
7. `npm logout` でnpmアカウントから抜ける。

更新の手順は以上ー。



## 自前でバージョン指定する方法

バージョンを自分でカウントアップして更新版を公開する方法。公式ドキュメントで推奨の `npm version` コマンドを使わなくても、とりあえず公開操作は出来るみたい。

`package.json` の version キーを更新（既存が0.0.1なら、0.0.2に）する。その状態で、初回公開時と同じ以下のコマンドを用いれば更新できる。なお、version キーが既存と同一だと、コマンドは失敗するので注意。

```sh
npm publish
```

「0.0.1→0.0.2」へ version キーを変更後に実施した場合、以下のようにして更新版が公開される。

![スクリーンショット 2018-07-11 06.40.01.png](https://qiita-image-store.s3.amazonaws.com/0/125588/0e8ca810-6b17-1c0c-fa20-cc01721d7cff.png)


# 参考リンク

npm パッケージを作って公開してみた
http://neos21.hatenablog.com/entry/2017/08/10/080000

npmのパッケージ公開入門
https://blog.katsubemakito.net/nodejs/publish_npm_package_for_beginners

初めてのnpm パッケージ公開
https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2

3分でできるnpmモジュール
https://qiita.com/fnobi/items/f6b1574fb9f4518ed520

npmの公式ドキュメント
https://docs.npmjs.com/