フリーランス
エンジニア
GitHub Packagesを使って自作ライブラリを管理しよう
業務でコードを書く際、似たような処理を別の業務で実装した経験がある方も多いのではないでしょうか。中には、それを自作のライブラリとして作成して、GitHubで管理するという形を取っている方もおられるでしょう。
では、実際にそれを複数のプロジェクトで使用する際はどのように行っているでしょうか。
今やほとんどのエンジニアが使っているGitHubですが、その機能のひとつにGitHub Packagesと呼ばれるパッケージホスティングサービスがあります。
今回はこちらを利用して、自作のJavaScript関数をnpmライブラリとして管理する手順をご紹介します。
GitHub Packagesとは
以前はGitHub Package Registryと呼ばれていたこのホスティングサービスですが、ひとことで言ってしまえば「作成したソフトウェアをGitHub上でパッケージとして管理することで、さまざまなプロジェクトで使えるようにしたよ」というものです。
プライベートリポジトリではプランによって料金が異なりますが、フリープランであってもストレージ容量500MBかつ月間データ転送量1GBまでであれば無料で使えます。
パブリックリポジトリに至っては完全に無料。太っ腹です。
GitHub Packagesに自作関数をデプロイする
今回はTypeScriptを使って簡単な関数を実装し、それを自分専用のライブラリとして作ってみましょう。
Package.jsonの設定
まずはPackage.jsonに以下の内容を記述していきます。
ついでにnpm installもやっておきましょう。
awesome-library/package.json{
"name": "@{GitHubのユーザーネーム}/{リポジトリ名}",
"version": "0.0.1",
"description": "GitHub Package sample",
"main": "dist/main.js",
"types": "dist/main.d.ts",
"publishConfig": {
"access": "restricted",
"registry": "https://npm.pkg.github.com/"
},
"repository": {
"type": "git",
"url": "git://github.com/{GitHubのユーザーネーム}/{リポジトリ名}.git"
},
"author": "{所有者の情報}",
"license": "UNLICENSED",
"devDependencies": {
"typescript": "^4.2.3"
}
}
ここで、いくつか重要なフィールドをピックアップして解説します。
name
@{GitHubのユーザーネーム}/{リポジトリ名}の形で入力します。
実際にライブラリをインストールする際も$ npm install @{GitHubのユーザーネーム}/{リポジトリ名}という形式になります。
version
ライブラリ自体のバージョンを管理します。今回はとりあえず0.0.1としておきました。
main
ライブラリが別のモジュールから呼び出された際に、どのファイルを参照するかを設定します。
今回はトランスパイルされた後のJSファイルを参照するので、dist/main.jsを指定しました。
typesフィールド
ライブラリの型定義ファイルを指定します。
publishConfig
npmで扱えるようにするため、registryにhttps://npm.pkg.github.comを指定します。
また、今回は自分専用=プライベートなライブラリなので、accessにはrestrictedを指定しておきます。
ちなみに複数のレジストリで公開したい場合は、publishConfigフィールドではなく.npmrcに記述する形になります。
tsconfig.jsonの設定
今回は最小限の設定だけ記述しました。
awesome-library/tsconfig.json{
"compilerOptions": {
"target": "es5",
"module": "umd",
"declaration": true,
"sourceMap": false,
"outDir": "./dist/",
"strict": true,
"moduleResolution": "node",
},
"exclude": [
"node_modules",
"dist"
],
"include": [
"src"
]
}
.gitignoreにdistを追加
リポジトリを作成する際、Node.jsのgitignoreテンプレートを選択している場合は不要ですが、もしそうでなければ.gitignoreにdistディレクトリを追加しておきましょう。
こちらはトランスパイル後のJSファイルと型定義ファイルが格納される予定ですが、トランスパイル自体は後述するGitHub Actionsで行います。
関数を作成する
今回は「引数として与えられた文字列の奇数番目だけを抽出した文字列を返す」という関数を作ってみます。
awesome-library/src/main.tsexport function getPartialText(text: string): string {
return text.split('').filter((_character, index) => index % 2 === 0).join('')
}
こんな感じでしょうか。
すごく簡単な内容ですが、これならビルドの時間も短いので練習にはもってこいです。
GitHub ActionsでPublishの設定を行い、Packageとして公開する
最後に、プッシュされたら自動でトランスパイル&Packageとして公開するGitHub Actionsを設定します。
.github/workflows/publish.ymlとして以下の内容を記述した設定ファイルを追加しましょう。
awesome-library/.github/workflows/deploy.ymlname: publish my library
env:
CI: true
on:
push:
branches:
- main
tags:
- "!*"
jobs:
publish:
name: Setup
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
# Nodeのバージョンを指定
- name: setup node
uses: actions/setup-node@v1
with:
node-version: 14.x
registry-url: https://npm.pkg.github.com
# 必要なモジュール(typescript)をインストール
- name: install node_modules
run: npm install
# トランスパイルを実行
- name: build
run: npx tsc
# パッケージとして公開する
- name: publish
run: npx can-npm-publish --verbose && npm publish || echo "No need to publish"
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# バージョン情報を環境変数として設定
- name: set version to env
run: node -p -e '`VERSION=${require("./package.json").version}`' >> $GITHUB_ENV
# バージョン情報持つタグを付与する
- name: add version tag
uses: pkgdeps/git-tag-action@v2
with:
version: ${{ env.VERSION }}
github_token: ${{ secrets.GITHUB_TOKEN }}
github_repo: ${{ github.repository }}
git_commit_sha: ${{ github.sha }}
git_tag_prefix: "v"
この際、secrets.GITHUB_TOKENという値を利用していますが、これは各リポジトリにデフォルトで備わっているトークンなので個別に設定する必要はありません。
ここまでの内容でプッシュしてみましょう。
リポジトリのActionタブを開くと、すでに先ほど設定したアクションが終了していました。
Codeタブに戻ってみるとPackagesの欄が追加されており、先ほどプッシュした内容がv0.0.1として正常にデプロイされたことがわかります。
デプロイされたライブラリを使う
次にデプロイされたライブラリを実際のプロジェクトに導入して利用する手順をご紹介します。
Personal Access Tokenを発行する
今回はプライベートなパッケージを対象としているので、それにアクセスするためのトークンを発行する必要があります。
公式の解説に従って設定ページを開きましょう。
パッケージの読み取りを行うだけなので、スコープはread:packagesにのみチェックを入れます。
NoteはわかりやすいようにREAD_PACKAGESとしてみました。
パッケージのインストール
Personal Access Tokenを発行したら、適当なプロジェクトを作成し、プロジェクトルートに.npmrcを作成して以下の内容を記述します。
nice-project/.npmrc@{GitHubのユーザーネーム}:registry="https://npm.pkg.github.com"
//npm.pkg.github.com/:_authToken={発行したPersonal Access Token}
これでプライベートなパッケージにアクセスできるようになりました。
あとは通常のNPMモジュールインストールと同様にnpm installすれば、node_modulesディレクトリにインストールされます。
$ npm i @{GitHubのユーザーネーム}/awesome-library
プロジェクトで使用する
それでは実際に使ってみます。
以下のスクリプトを実行し、AAAAと表示されれば成功です。
nice-project/src/index.tsimport { getPartialText } from '@{GitHubのユーザーネーム}/awesome-library'
console.log(getPartialText('ABABABA'))
$ npx tsc src/index.ts // ←dist/index.jsにトランスパイルします
$ node dist/index.js
AAAA
期待通りに動きました。
関数名にマウスオーバーすると型の情報も見られるので、型定義ファイルもきちんと参照できているようです。
パッケージのアップデート
ここで先ほど実装したライブラリに、「奇数番目or偶数番目の文字列を引数によって選択できる」という新機能を実装したくなりました。
早速実装してみましょう。
awesome-library/src/main.tsexport function getPartialText(text: string, target: 'odd' | 'even'): string {
if(target === 'odd') {
return text.split('').filter((_character, index) => index % 2 === 0).join('')
} else {
return text.split('').filter((_character, index) => index % 2 !== 0).join('')
}
}
新機能を追加したのでマイナーアップデートという扱いにしましょう。
手動で書き換えることもできますが、npmにはパッケージのバージョンを管理するコマンドがあるのでそれを利用します。
$ npm version minor
$ 0.1.0
$ git log --max-count 2 --oneline
10b8d80 (HEAD -> main, tag: v0.1.0) 0.1.0
b466945 feat: 奇数番目か偶数番目かを選べる機能を実装
gitのログを確認してみましょう。
package.jsonのバージョンが更新され、v0.1.0として新たにタグが作成されていると思います。この状態でプッシュしましょう。
Releaseの欄が2 tagsになり、Packages欄のバージョンも0.1.0になっています。
どうやらきちんとアップデートできたようです。
まとめ
昨今はnpmライブラリが充実しており、欲しい機能は探せば見つかることが多いと思います。
しかし、公開されているライブラリでは機能が不足していたり、不要な機能が多すぎたりする場合、自作のライブラリで解決するという手段は選択肢として大いにあると思います。
そんなときには、ぜひGitHub Packagesを利用して便利に使いまわしていきましょう。
Takumi.K
サービス開発にも携わるフリーランスフロントエンドエンジニア。