こんにちは、フロントエンドエンジニアをしている やまたろう です。
今回は、進行中のプロジェクトでUIライブラリを作ることになったので、Github Packagesを活用して社内のGithub組織のメンバーだけに公開するnpmパッケージの作り方を紹介します。

Github Packagesとは

Githubが提供するパッケージレジストリサービスです。
npm・Docker・Nuget・Maven・Gradleなど様々な用途のレジストリが存在します。Nugetまでカバーされているのは流石ですね。
パブリックなリポジトリでは無料で利用でき、プライベートなリポジトリでもストレージやデータ転送量に制限はありますが無料で始めることができます。お試しや外に出したくないものの個人開発で活用できそうです。

npm公式のリポジトリと比較して、Privateリポジトリであっても無料で始められる点やアクセス権限と編集権限ユーザーをGithubで一元管理できたり、Github Actionsとの連携のしやすさが魅力的です。Github Packages公式ページ

プロジェクト準備

Vite + Vue3 + Typescript のテンプレートを利用してコンポーネントをビルドするプロジェクトを作成します。
開発環境はNode.jsのLTSのバージョンが入っていればよいと思います。執筆時点では16.17.0です。
まずは、以下のコマンドでプロジェクトを作成します。

npm init vite@latest <YOUR_PROJECT_NAME>


vueのほかReactなどプロジェクトを作成できる

生成後、プロジェクトの構造は以下のようになっているので、必要最低限なものを残して他は全て削除します。


テンプレートの初期状態


削除後の状態

src 配下にあったファイルは HelloWorld.vue vite-end.d.ts 以外は削除して HelloWorld.vue をExportする index.ts を作成しています。
実際にUIライブラリを作成する際は storybookなどの設定や、AtomcDesignなどのデザインパターンを取り入れると思います。

次に、viteにビルド用の設定を追記していきます。初期状態は非常にシンプルなものになっていて何も設定をしていない場合エントリポイントの index.html を探して依存関係を見つけていきます。

// vite.config.ts - 初期状態

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
});

vite.config.js – 初期状態

// vite.config.ts - 追記後

import { resolve } from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.ts"),
      name: "sample",
      formats: ["es"],
      fileName: (ext) => `index.${ext}.js`,
    },
    rollupOptions: {
      external: ["vue"],
      output: {
        exports: "named",
        globals: { vue: "Vue" },
      },
    },
  },
});

vite.config.js – 追記後

build プロパティでエントリポイントや出力するモジュールの種類やファイルを設定したのち、vue や react といった利用先のモジュールをバンドルしないような設定を追加します。
path moduleの型が見つからない場合は @types/node モジュールを追加してください。
これでビルドできるようになりましたが、Typescriptの型定義ファイルの出力をするためには別でプラグインを読み込む必要があるので追加・設定します。

yarn add -D vite-plugin-dts
// vite.config.ts - vite-plugin-dts 追加後

import { resolve } from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import dts from "vite-plugin-dts";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), dts({ insertTypesEntry: true })],
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.ts"),
      name: "sample",
      formats: ["es"],
      fileName: (ext) => `index.${ext}.js`,
    },
    rollupOptions: {
      external: ["vue"],
      output: {
        exports: "named",
        globals: { vue: "Vue" },
      },
    },
  },
});

これでビルドに関する準備は全て整ったので、早速実行してみます。

無事ビルドが成功して、プラグインによる型定義ファイルの出力も成功しています。

作成したプロジェクトをGithubのPriavate Repositoryに登録して準備は完了です。

Github Packagesへの公開

始めに、package.jsonにpublish用の設定を追加していきます。
以下を参考にエントリポイントやPublish先のレジストリを指定します。注意点として nameプロパティにGithubのユーザーもしくはOrganization名をパスで含める必要があります。

// package.json

{
  "name": "@<Githubユーザー名 または Github組織名>/package-sample",
  "version": "1.0.0",
  "scripts": {
    "prepublishOnly": "npm run build",
    "build": "rimraf dist && vue-tsc --noEmit && vite build"
  },
  "peerDependencies": {...},
  "devDependencies": {...},

  "main": "dist/index.es.js",
  "types": "./dist/index.d.ts",
  "module": "./dist/index.es.js",
  "exports": {
    ".": "./dist/index.es.js",
    "./style": "./dist/style.css"
  },
  "publishConfig": {
        "access": "restricted",
    "registry": "https://npm.pkg.github.com/<ユーザー名 または Github組織名>"
  }
}

普段はパッケージを利用する人間なので、プロパティ設定時の挙動などがわからず 公式ドキュメントにかなりお世話になりました。
また、 prepublishOnly という名前のスクリプトを設定することで publishの直前に実行するコマンドを仕込むことができるようなので、ビルドコマンドを設定しています。
これで大体の設定が完了したので、Github ActionsでPublishするようワークフローを作成します。

完成形は以下の通り。

# .github/workflows/publish.yml

name: publish package

on:
  release:
    types: [created]

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16
          registry-url: https://npm.pkg.github.com/

      - name: Package install
        run: yarn install --frozen-lockfile

      - name: Update package.json version
        uses: jossef/action-set-json-field@v1
        with:
          file: package.json
          field: version
          value: ${{ github.event.release.name }}

      - name: Publish package
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

ポイントごとにいくつか解説していきます。
トリガーは、リリースの作成時に指定していますが、プルリクエストやブランチによるトリガーももちろん可能なので運用に応じて変更可能です。
今回はGithubのリリース機能との相性が良さそうだったので設定しています。

on:
  release:
    types: [created]

ジョブのランタイムの設定で、Github Packagesに書き込む権限を与える必要があります。これがないとパッケージをパブリッシュする際にエラーが発生します。
この設定で GITHUB_TOKEN に与えるアクセス権限を設定しているようです。

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: read

Node.js のセットアップを行う際にレジストリをGithub Packagesに指定します。

    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 16
          registry-url: https://npm.pkg.github.com/

ステップの中で package.json に記載されているバージョンを書き換えています。今回はリリース名をそのまま流用。

      - name: Update package.json version
        uses: jossef/action-set-json-field@v1
        with:
          file: package.json
          field: version
          value: ${{ github.event.release.name }}

最後にパッケージのパブリッシュを行います。 NODE_AUTH_TOKEN にGithubの認証トークンを入れて終了です。認証トークンの管理を自分で行う必要がないのが快適でよいですね。
これで全ての設定が完了しました。

早速、新しいリリースを作ってパッケージが作成されることを確認します。
リポジトリのトップページから [Release] → [Create a new Release] と選択して、リリース作成画面に遷移します。
そこでタグ情報とリリース名を指定してパブリッシュを実行。

暫くするとGithub Actionsが動作し、パッケージが登録されました。

おわりに

Github Packagesを利用することで最低限の設定でパッケージの管理を行うことができました。
冒頭でも述べた通り、Githubのアカウントがあれば利用できる点が個人でも企業でも使いやすいと私は感じているので、複数サービスのアカウントや認証トークンを管理して疲弊している方は思い切って移行すると楽になれるかもしれません。
最後までお読みいただきありがとうございました。

SHARE

  • facebook
  • twitter

SQRIPTER

AGEST Engineers

AGEST

記事一覧

AGESTのエンジニアが情報発信してます!
AGESTのサービスやソリューションのお問い合わせページはこちらです。

株式会社AGEST

Sqriptsはシステム開発における品質(Quality)を中心に、エンジニアが”理解しやすい”Scriptに変換して情報発信するメディアです

  • 新規登録/ログイン
  • 株式会社AGEST