TOMILOG

npmパッケージの公開&自動化の手順

npmパッケージの公開&自動化の手順
| 2020/04/17

はじめてnpmパッケージを公開しました!
パッケージ公開にあたって調べた、公開の仕方とパッケージの準備、それとCircleCIを使った自動化の手順をまとめます。

公開の手順

npmパッケージの公開までのおおまかな手順なこんな感じ

  • 公開するパッケージの準備(ビルドされたファイル)
  • パッケージ情報を入力(packege.json)
  • パッケージの使い方説明(README.md など)
  • npmアカウントを作成
  • npmに公開!(Githubにpushしたら自動的にビルド&公開されるように)

使用者の環境に合わせるために3種類の規格に沿ったファイルを用意すること、package.jsonの書き方、CircleCIでの自動化
主にここらへんをまとめていきます。

公開するパッケージの準備

公開するにあたって、パッケージとなるソースコードを書いて完成!というわけにはいきません。
Javascriptといっても様々な規格があり、パッケージをインストールしてくれる人によって使っている規格が異なります。

const VueAddEventListener = require('vue-add-event-listener');

require()を使うCommonJS

import VueAddEventListener from 'vue-add-event-listener';

importを使うECMAScript

<script src="https://unpkg.com/vue-add-event-listener"></script>

ブラウザから直接利用

最低限、この3つを用意すると良いでしょう。

3つの規格をビルドする

好きなように書いたindex.jsyarn buildで、これら3つのJS規格がビルドされるようにします。

./index.jsをビルドして、
./dist/index.cjs.js, ./dist/index.esm.js, ./dist/index.umd.jsを出力します。

CommonJS => ./dist/index.cjs.js
ECMAScript => ./dist/index.esm.js
ブラウザ用 => ./dist/index.umd.js

今回は、手軽にビルドできるRollupを用います。(Webpackやparcelを使っても構いません。)

$ yarn add -D rollup @rollup/plugin-buble
import buble from '@rollup/plugin-buble' // 適切にブラウザをサポートするトランスパイラおよびポリフィル

export default {
    input: 'index.js', // Path relative to package.json
    output: [
      {
        file: 'dist/index.umd.js',
        format: 'umd',
        name: 'VueAddEventListener',
      },
      {
        file: 'dist/index.esm.js',
        format: 'es',
      },
      {
        file: 'dist/index.cjs.js',
        format: 'cjs',
      },
    ],
    // 依存モジュールを含めたくない場合に設定する
    // external: ['vue'],
    plugins: [
        buble(), // ES5 へトランスパイルする
    ],
}

ビルドのための設定はこれだけです。

そして、package.jsonにyarn buildで実行できるように追記します。

{
  "scripts": {
    "build": "rollup --config build/rollup.config.js"
  }
}

以上でビルドは完了です。

$ yarn build
yarn run v1.22.4
$ rollup --config build/rollup.config.js

index.js → dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js...
created dist/index.umd.js, dist/index.esm.js, dist/index.cjs.js in 31ms
✨  Done in 0.67s.

package.jsonの書き方

npmに公開される情報は、package.jsonに書かれた内容とREADME.mdの内容で構成されます。
README.mdについての説明は省きます。(英文がんばってください。。。)

今回公開したpackage.jsonの中身はこちら。
それぞれ見ていきましょう。

{
  "name": "vue-add-event-listener",
  "version": "1.0.3",
  "description": "AddEventListener plugin for Vue",
  "main": "dist/index.cjs.js",
  "module": "dist/index.esm.js",
  "unpkg": "dist/index.umd.js",
  "scripts": {
    "build": "rollup --config build/rollup.config.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/bonos103/vue-add-event-listener.git"
  },
  "keywords": [
    "vue",
    "addEventListener"
  ],
  "author": "Ryohei Tomiyama",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/bonos103/vue-event-listener/issues"
  },
  "homepage": "https://github.com/bonos103/vue-event-listener#readme",
  "devDependencies": {
    "@rollup/plugin-buble": "^0.21.2",
    "rollup": "^2.6.0",
    "vue": "^2.6.11"
  }
}

name

まずは、name。こちらがパッケージ名になる重要な部分です。

npm install vue-add-event-listener などで使われる名前になります。

注意するべき点は、すでに公開されているパッケージと名前が類似していると、公開する際にエラーになります。

具体的には、- . _ を無視した名前が重複するパッケージ名は使用できません。

vue-add-event-listener vue-addeventlistener vue_add_event_listener vue.add-event-listener は同じ名前とみなされます。

description

npmサイトのパッケージ一覧に表示される説明文

npm_description-1

version

パッケージのバージョン
npmパッケージを更新したいときに、このバージョンも変更しないと、npm上に反映されません。
どんなに小さい修正だろうと、1.0.1 → 1.0.2 のように変更してください。

main, module, unpkg

ビルドした3つのファイルを指定します。
これらに指定することで、各環境に合わせて使われるファイルが自動で変わります。

"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"unpkg": "dist/index.umd.js",

main

CommonJSの環境で使うファイルを指定。

module

ECMAScriptの環境で使うファイルを指定。

unpkg

ブラウザから使うファイルを指定。
これを指定すると、unpkg.comのサイトからファイルにアクセスできるようになります。
https://unpkg.com/vue-add-event-listener

ここで注意が必要なのが、unpkgに指定したファイルはGithubのリポジトリ入れておく必要があります。
.gitignoreでdistディレクトリを無視する設定をしている場合は、!dist/index.umd.jsを追記してあげてください。

repository

npmサイトの右側にRepositoryとして、表示されます。

  "repository": {
    "type": "git",
    "url": "git+https://github.com/bonos103/vue-add-event-listener.git"
  }

npm_repository

homepage

npmサイトの右側にHomepageとして、表示されます。

npm_homepage-1

keywords

npmサイトのパッケージ一覧に表示されます。
検索などにも引っかかるものなので、しっかりと指定しましょう。

npm_keywords-1

とりあえず、これだけ指定しておけばnpmに公開するのに支障ないと思われます。

npmの公開方法

公開自体には難しいことはなく、npmアカウントを作成して、npm login して npm publishすれば公開できます。
自動化せずにコマンドから公開する手順は、こちらの記事が参考になります。

CircleCIでビルド〜公開までを自動化する

ここまで読めばnpmを公開すること自体はできますが、今回はGithubのレポジトリにmasterブランチをpushしたとき、CircleCIで3つのファイルを生成するビルドが行われて、npmに公開されるところまでを自動化したいと思います。

CircleCIの実行ファイルはこちら。

version: 2
defaults: &defaults
  docker:
    - image: circleci/node:12.14.1
  working_directory: ~/repo
jobs:
  install:
    <<: *defaults
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ .Branch }}-{{ checksum "yarn.lock" }}
            - v1-dependencies-{{ .Branch }}-
            - v1-dependencies-
      - run: yarn
      - save_cache:
          key: v1-dependencies-{{ .Branch }}-{{ checksum "yarn.lock" }}
          paths:
              - node_modules/
      - persist_to_workspace:
          root: ~/repo
          paths:
            - .
  build:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/repo
      - run: yarn build
  
  deploy:
    <<: *defaults
    steps:
      - attach_workspace:
          at: ~/repo
      - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/repo/.npmrc
      - run: npm publish

workflows:
  version: 2
  deploy-vue-event-listener:
    jobs:
      - install:
          filters:
            branches:
              only: /^master/
      - build:
          requires:
            - install
          filters:
            branches:
              only: /^master/
      - deploy:
          requires:
            - install
            - build
          filters:
            branches:
              only: /^master/

実行ファイルの説明

jobs

実行するジョブは3つ。
node_modulesをインストールするinstall
3つのファイルを生成するbuild
npmに公開するdeploy

workflows

これらのジョブをworkflowsを使ってinstall → build → deployの順番でジョブが実行されるようにしています。

workflows内でrequiresを指定すると、指定されたジョブが実行完了されたあとに実行するようにしてくれます。

requires:
  - install
  - build

filtersの設定で、branchがmasterのときだけ実行するようにしています。

filters:
  branches:
    only: /^master/

また、workflowsを使うときに重要なのが、persist_to_workspaceとattach_workspaceです。

persist_to_workspaceでディレクトリを共有して、とattach_workspaceでそのディレクトリを参照することができます。

この設定によって、installで生成された、node_modules/がその後に続く、build, deployのジョブから参照できるようになります。

もしこの設定がなかったら、ジョブはそれぞれ別のコンテナ(空間)で実行されるので、buildを実行しても、node_modulesをインストールできていないので、失敗します。

npm publishの準備

npm publish をする前にnpmのログイン情報が入っている、.npmrcを作成しています。
このときに必要なTokenの取得方法とCircleCIへの設定方法を説明します。

まずは、npmの会員登録を行ってください。

会員登録が完了したら、パソコンのターミナルからnpm login します。

npm_login-1

ログインが完了しました。

そしたら、Tokenを取得するために、cat ~/.npmrc します。

npm_token-1

ここに表示される06451a9f….がTokenになります。

続いて、CircleCIからこのTokenが使えるように環境変数に設定します。
(まだCircleCIとレポジトリを連携してない場合はしてください。)

プロジェクトの設定画面に進んでください。

npm_circleci_setting

設定画面の「Environment Variables」を開き、「Add Variable」ボタンを押して、環境変数を追加します。

Name: NPM_TOKEN
Value: { 先程取得したToken }

npm_environment

以上の設定で、ビルド〜公開までを自動化が完了になります。
あとは、masterブランチをpushすれば、ジョブが実行されてnpmに公開されます!

npm_jobs

1回のpushで3つのjobが動きました!
そして、npmにも公開されました!🎉
https://www.npmjs.com/package/vue-add-event-listener

npm_publish-1

結構長い道のりになってしまいましたが、良い経験になりました。
おつかれさまでした。

とみー
フリーランス ← フルスタックエンジニア ← Webデザイナー。2018年、長野県に移住しフルリモートで様々サービス開発に携わるフロントエンジニアとして活動中。開発で得た知見を発信していきます。