独自の npm registry を使う

標準の https://www.npmjs.com 以外の場所で Javascript ライブラリを管理したい場合、自分で npm registry を運用する必要がある。独自 npm registry として使える物として Artifactry や verdaccio など色々あるようなので調べた。

## まとめ

http://localhost:4873 に独自 npm registry がある時

* レポジトリの設定
  * パッケージの .npmrc に `registry=http://localhost:4873` と書く。
* パッケージの公開 (要するに独自 npm registry だからと言って特に特殊な所は無い)
  * `npm adduser`
  * `npm publish`
* パッケージのインストール (Verdaccio の場合独自 registry に無ければ npmjs を探す)
  * `npm install`

## node の package と module とは何か?

まず基本的な復習として、node の module や package とは何か確認する ([Understanding Packages and Modules](https://docs.npmjs.com/getting-started/packages))。だいたいは package == module だが、違う状況もある。

* package とは、package.json を含むディレクトリや zip ファイル、URL 等の事。
* module とは、 require() で読み込むファイルやディレクトリ理の事。
  * package.json を含まない module があってもよい。

## package の作り方と module として呼び出す方法

典型的には以下のコマンド列で `hoge` という名前の package を作る。

```
mkdir hoge
cd hoge
npm init
```

この際に、package name を `@(npm アカウント名)/hoge` のようにして @ に続いて後述する npmjs のアカウント名をつける (例: `@propella/hoge`) と後で package を公開する時に名前が被らなくて便利。これを [scoped packages](https://docs.npmjs.com/misc/scope) と呼ぶ。

`hoge` を利用する側は `npm install ../hoge` のようにするとシンボリックリングが `node_modules` 内に貼られる。ファイルパス以外の方法で参照すると、`node_modules` 内にコピーが置かれる。パッケージを代表する Javascript ファイルを package.json の `main` に記述しておく。

    "main": "main.js",

例えば、以下のような main.js があると

```
exports.hoge = function() {
    return 'hoge';
}
```

呼び出し側は、

    const hoge = require('hoge');
    console.log(hoge.hoge());

のようにして呼び出す。`require()` は指定されたディレクトリの `package.json` の `main` に記述した Javascript ファイルを実行し、`exports` に登録したオブジェクトを返す。([Folders as Modules](https://nodejs.org/api/modules.html#modules_folders_as_modules))

## package を公開する

作成した package を標準の npmjs.com に公開するには npm publish を使う ([How to Publish & Update a Package](https://docs.npmjs.com/getting-started/publishing-npm-packages))。

npmjs にアカウントが無ければ、まず https://www.npmjs.com/signup で登録して、email の認証を済ます。

まず `npm adduser` する。サーバ名と autoToken の組がサーバごとに `~/.npmrc` に置かれるので複数のサーバに同時にログイン出来る。

```
$ npm adduser
Username: xxx
Password: yyy
Email: (this IS public) zzz@zzz
```

`npm adduser` には `npm login` という Alias もある。アカウントが無ければ作る。あればログインという動作になっている。

公開するには

    npm publish

のようにする。もしくは package 名が scoped の場合 (@ がついてる場合)

    npm publish --access public

のようにする。

publish の時 .npmignore に書いてあるファイルは除かれる。([Keeping files out of your package](https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package))。

## 公開した package を削除する

    npm unpublish --force package名

## package をプライベートな Verdaccio に公開する

プライベートな npm registry としてオープンソースの物では [verdaccio](https://github.com/verdaccio/verdaccio) が良いらしいので試した。

docker があるなら以下で起動する。

    docker run -it --rm --name verdaccio -p 4873:4873 verdaccio/verdaccio

ユーザ追加とログイン。

    npm adduser --registry http://localhost:4873

パッケージを公開。Vardaccio の場合 `--access public` は不要。

    npm publish --registry http://localhost:4873

このレポジトリにある hoge を npm install する方法

    npm config set registry http://localhost:4873
    npm install hoge

参考

* [Ways to have your private npm registry — and a final DIY solution](https://medium.com/engenharia-noalvo/ways-to-have-your-private-npm-registry-and-a-final-diy-solution-eed001a88e74)
* [プライベートnpmレジストリを無料で作る——「Verdaccio」という選択肢](https://www.webprofessional.jp/private-npm-packages-verdaccio/)

## ある scope のパッケージだけを独自の npm registry からインストールする。

Vardaccio だとローカルに無いパッケージを自動的に npmjs に取りに行くので必要無い気がするが、`@piyo/hoge` のようにある scope のついたパッケージだけを独自の npm registry からインストールする事も出来る ([Associating a scope with a registry](https://docs.npmjs.com/misc/scope#associating-a-scope-with-a-registry))。

    npm config set @piyo:registry http://localhost:4873
    npm install @piyo/hoge

`npm config set ...` の代わりに `npm adduser --registry http://localhost:4873 --scope=@piyo` のようにしても同じ事が起こる。

念の為だが、この場合でも `@piyo/hoge` という名前のパッケージが対象の npm registry に必要だ。つまり、対象の npm registry にある `hoge` というパッケージを `@piyo/hoge` という名前で install 出来るわけでは無い。

ちなみに、Verdaccio には user group のような物は無い。scope のは単なる名前なので、npmjs と異なり account や organization に紐付いているわけではない。アカウントを持っていれば誰でも @fuga でも @piyo でも作れる。

## とあるプロジェクトの中だけ独自の npm registry を使う

npm config の設定は [npmrc](https://docs.npmjs.com/files/npmrc) というファイルに置かれる。このファイルは ~/.npmrc の他 /path/to/my/project/.npmrc のように使いたいパッケージに置くことが出来るので、あるプロジェクトだけ独自の npm registry を使いたい場合

    registry=http://localhost:4873

のような一行をパッケージの中の .npmrc に置けば良い (.npmrc は package.json と同じディレクトリに置く必要があるらしい)。こうすると `npm publish` 時の --registry も不要になる。

## artifactory を npm registry として使う方法 (TBD)

多分 Verdaccio と同じだが作業中。