プライベートnpmレジストリ「Verdaccio」をDockerで立てて、vueコンポーネント登録してみる

# 背景
Vue.jsで大きなプロジェクトを開発する時の事を考えてる最中。そのプロジェクトだけで使用する共通モジュール（全世界公開はしない）をどうするかが課題の一つ。
mavenでのprivate javaリポジトリの様なものが無いか調べてたら、Verdaccio というものがそれに該当するらしい。試しておきたい。

# 前説
基本関係プロジェクトとかはDockerコンテナで構築しています。結果的に以下３つのDockerコンテナを使用しているので、コンテナ内、というのがどのコンテナかはお察ししてもらえると有り難いです。

 - Verdaccio サービスを起動しているコンテナ（コンテナ名 verdaccio）
 - vue-sfc-rollup を使用してコンポーネント作成するプロジェクトのコンテナ（コンテナ名 vuecomptest01）
 - コンポーネントをインストールするプロジェクトのコンテナ（コンテナ名 vueprj-test01）

ホストとは、これらのコンテナが起動しているホストマシンの事です。

# Verdaccioを構築してみる
やっぱりDockerで構築したい。Dockerfileを作り始めようと思ったが、既に公式Dockerイメージが無いか探してみた。そしたら、公式イメージが存在した。
https://verdaccio.org/docs/en/docker.html
早速説明ページ通りにトレース。

Docker使うとはいえ、永続領域を持つサービスなので、それ用のフォルダ用意。

```bash:ホスト側の永続領域フォルダ作成
sudo mkdir -p /var/opt/verdaccio
sudo chmod 777 -R /var/opt/verdaccio
```

起動用のシェル、launch-verdaccio.shを作る。

```bash:launch-verdaccio.shの中身
#! /bin/bash

V_PATH=/var/opt/verdaccio;

docker run -it --rm -d --name verdaccio \
  -p 4873:4873 \
  -v $V_PATH/conf:/verdaccio/conf \
  -v $V_PATH/storage:/verdaccio/storage \
  -v $V_PATH/plugins:/verdaccio/plugins \
  verdaccio/verdaccio
```

```bash:権限変更しておく
chmod 755 launch-verdaccio.sh
```

```bash:Docerイメージ取得＆起動
sudo docker pull verdaccio/verdaccio
```

[Verdaccioを使って簡単local npm registryを構築する](https://qiita.com/gn5r/items/6716fb13f51b07b1dd55) を真似て、config.yaml作成。
[公式ページ](https://verdaccio.org/docs/en/configuration)も参照して少し修正。

```bash:config.yaml作成
vim /var/opt/verdaccio/conf/config.yaml
```

```yaml:config.yaml
storage: /verdaccio/storage
plugins: ./plugins

web:
  title: Verdaccio

auth:
  htpasswd:
    file: ./htpasswd

uplinks:
  npmjs:
    url: https://registry.npmjs.org/
  local:
    url:  http://localhost:4873/

packages:
  '@*/*':
    # scoped packages
    access: $all
    publish: $authenticated
    unpublish: $authenticated
  '**':
    access: $all
    publish: $authenticated
    unpublish: $authenticated
    proxy: npmjs

server:
  keepAliveTimeout: 60

middlewares:
  audit:
    enabled: true

listen: 0.0.0.0:4873
```

```bash:起動
sudo ./launch-verdaccio.sh
```

http://localhost:4873/ へアクセスしてみる。何も登録されてない事が表示された（画面ショット取り忘れ）。


# Verdaccio初期セットアップ

```bash:コンテナログイン
sudo docker exec -it --user root verdaccio /bin/sh
```

```bash:ログインユーザーの作成
npm adduser --registry http://localhost:4873/
```
入力を求められるので、適当にユーザーID、パスワード、メールアドレス（xxxx@yyy.zzz形式）を入力。
※後々使うので忘れない事！！！

# 登録テスト用ライブラリ作成

[Vue Componentをnpmパッケージ経由で配布する](https://qiita.com/otsumitsu/items/021ba98f849bff614ab0)
によると、vue-sfc-rollup というモジュールを使うと簡単にコンポーネント公開環境が出来るらしい。
[vue-sfc-rollup公式ページ](https://github.com/team-innovation/vue-sfc-rollup) を参考にする。

### dockerで環境準備

```bash:ホスト側フォルダ作成
mkdir -p ~/vuecomptest01/component
cd ~/vuecomptest01
```

設定ファイル作成（~/vuecomptest01 直下に配置）

```yml:docker-compose-vueini.yml
version: '3.7'
services:
  frontvue:
    build:
      context: .
      dockerfile: Dockerfile-vueini
    ports:
      - 8080:8080
    volumes:
      - ./component:/component
    container_name: vuecomptest01
    tty: true
```

```dockerfile:Dockerfile-vueini
FROM node:12.18.1-alpine

MAINTAINER silverbox

WORKDIR /component

RUN apk update
RUN apk add curl
RUN npm install -g @vue/cli@4.4.1
RUN npm install -g @vue/cli-init@4.4.1
```

```bash:コンテナ起動＆コンテナへログイン
sudo docker-compose -f docker-compose-vueini.yml build
sudo docker-compose -f docker-compose-vueini.yml up -d
sudo docker exec --user root -it vuecomptest01 /bin/sh
```

```sh:コンテナ内
/component # npm install -g vue-sfc-rollup
/component # sfc-init
```

開発する種類を聞かれるので、選択する。今回は簡単にSingle Componentを選択。後はコンポーネントとかの名前を聞かれます。

```console:sfc-initでの選択肢
? Is this a single component or a library? › - Use arrow-keys. Return to submit.
❯   Single Component
    Library

# TypeScript か JavaScript かも聞かれます。今回は簡単にJavaScriptを選択。
? Will this component be written in JavaScript or TypeScript? › - Use arrow-keys. Return to submit.
❯   JavaScript
    TypeScript

```

```console:sfc-initでの選択肢最終状態
/component # sfc-init
✔ Is this a single component or a library? › Single Component
✔ What is the npm name of your component? … my-test-component01
✔ What is the kebab-case tag name for your component? … my-test-component01
✔ Will this component be written in JavaScript or TypeScript? › JavaScript
✔ Enter a location to save the component files: … ./my-test-component01

  Init is complete, your files have been generated and saved into the directory you specified above.
  Within that directory, use src/mytest-component.vue as a starting point for your SFC.
  When you're ready, run `npm run build` to generate the redistributable versions.
```

こんな感じのフォルダ＆ファイル構成でサンプルも同時に作成されます（すごい助かる）。
※ホスト側からマウントされているフォルダをVSCodeで見てる状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/1f495bb7-8e05-2623-15d6-768e010cb9c2.png)

```sh:モジュールインストール＆サンプル起動（コンテナ内）
/component # cd my-test-component01
/component/my-test-component01 # npm install
/component/my-test-component01 # npm run serve
```

ホストから、サンプルぺーjにアクセスできます。
/component/my-test-component01/dev/serve.vue をいじればサンプルページも編集出来そうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/393e6fd6-1881-c233-c654-30937ee0a7a6.png)

Ctrl+Cで開発モード終了してビルドします。

```sh:モジュールインストール＆サンプル起動（コンテナ内）
/component/my-test-component01 # npm run build
```

distフォルダ内にビルド成果物が生成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/06483294-8eef-a647-ac7d-6d9bbf79f28d.png)

公式ページによると、「# Ready to publish!」だそうで。

# プライベートリポジトリにpublish

DockerホストのIPを指定しているが、Verdaccioコンテナとつながってるので大丈夫。
もちろん、上の方でセットアップしたVerdaccioコンテナは起動したままです。

```sh:ログインしておく（コンテナ内）
npm login --registry http://{ホストのIP}:4873
```
Verdaccio初期セットアップで登録したユーザーのID/Pass/e-mailを入力

```sh:publish実行
/component/my-test-component01 # npm publish --registry http://{ホストのIP}:4873
npm notice 
npm notice package: my-test-component01@1.0.0
npm notice === Tarball Contents === 
npm notice 8.7kB dist/my-test-component01.esm.js
npm notice 3.7kB dist/my-test-component01.min.js
npm notice 8.2kB dist/my-test-component01.ssr.js
npm notice 1.4kB package.json                   
npm notice 1.7kB src/my-test-component01.vue    
npm notice === Tarball Details === 
npm notice name:          my-test-component01                     
npm notice version:       1.0.0                                   
npm notice package size:  5.6 kB                                  
npm notice unpacked size: 23.7 kB                                 
npm notice shasum:        a7c10cbacae6c99acc8ad1256e2c533cb18a600a
npm notice integrity:     sha512-YO60lOmRGhoVZ[...]t+pCFzJCQm6bw==
npm notice total files:   5                                       
npm notice 
+ my-test-component01@1.0.0
```

プライベートリポジトリに登録されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/a198e52e-8683-ba11-f8fd-11d9b9f11060.png)


# プライベートリポジトリを使ってみる

以前書いた記事、[Vueを複数人で開発する環境を試してみた](https://qiita.com/silverbox/items/5290615c490e9c52f14c) で使用したコンテナ環境で試してみる。

```sh:コンテナにログイン
sudo docker exec --user root -it vueprj-test01 sh
```

```sh:レジストリ指定＆インストール（コンテナ内）
npm config set registry http://{ホストのIP}:4873
npm install my-test-component01

/app # npm install my-test-component01
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/watchpack-chokidar2/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/webpack-dev-server/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ my-test-component01@1.0.0
added 1 package in 16.91s

45 packages are looking for funding
  run `npm fund` for details
```

ちょっとWarning出てるけどインストール出来ました。

# 参考にさせてもらったページ
[Verdaccioを使って簡単local npm registryを構築する](https://qiita.com/gn5r/items/6716fb13f51b07b1dd55)
[verdaccioでprivateなnpmリポジトリを作成](https://qiita.com/mtokiwa/items/1bc22a2270e4408d4cdd)

[Vue コンポーネントを npm パッケージ化する](https://jp.vuejs.org/v2/cookbook/packaging-sfc-for-npm.html)
[Vue CLI3でコンポーネントをnpmのモジュールにする](http://cream-worker.blog.jp/archives/1073223386.html)
[javascript - Vueコンポーネントを外部プロジェクトに公開する](https://ja.coder.work/so/javascript/1533701)
[【Vue.js】業務で開発した自作ライブラリをnpmに公開してみた](https://allabout-tech.hatenablog.com/entry/2018/03/22/124300)
[Vue Componentをnpmパッケージ経由で配布する](https://qiita.com/otsumitsu/items/021ba98f849bff614ab0)
[vue-sfc-rollup公式gitリポジトリ](https://github.com/team-innovation/vue-sfc-rollup)