例えばフロントエンドとバックエンドの両方を TypeScript で開発している場合、型定義を共有したい場面があるはず。

両方に同じコードをコピペすることで当座は解決はできますが、長期的に考えるのであれば同じ1つのファイルを参照するようにしておくべきです。

方法はいろいろありますが、ここでは共通するコードを別のパッケージとして開発し、それを GitHub Packages を通じて利用する方法をご紹介します。

まず、パッケージを作成・更新する側の流れを書き、次に、そのパッケージを利用する側の流れを記述します。

パッケージを作成・更新する

1. GitHub のリポジトリを作成する

以降 “harry-potter” という GitHub アカウントのユーザで操作すると想定します。

ここでは harry-potter/example-core というリポジトリを作成しました。

2. パッケージを作成する

ファイルを用意する

まずはパッケージの元となるファイルを作成します。

全体の構成

├ node_modules/
├ package.json
├ tsconfig.json
├ .gitignore
└ src/
  └ index.ts

package.json

{
  "name": "@harry-potter/example-core",
  "version": "0.0.1",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "files": ["dist"],
  "devDependencies": {
    "typescript": "^4.0.0"
  },
  "scripts": {
    "build": "tsc"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./dist",
    "target": "ES2015",
    "module": "commonjs",
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

.gitignore

node_modules/
dist/

src/index.ts

export type Summable = [number, number];

export function sum([a, b]: Summable): number {
  return a + b;
}

ビルドする

npm run build

dist ディレクトリにビルドされたファイルが作成されます。

└ dist/
  ├ index.js
  ├ index.js.map
  ├ index.d.ts
  └ index.d.ts.map

3. GitHub のアクセストークンを生成する

FYI: https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

GitHub Packages にパッケージをパブリッシュするために GitHub のアクセストークンが必要になります。

GitHub の以下からアクセストークンを生成します。

> Settings
  > Developer settings
    > Personal access tokens
      > Generate new token

トークンの名称と権限のスコープを指定する必要があります。

  • 名称:お好みで。例えば GitHub Packages で良いでしょう。
  • 権限のスコープ:write:packages を選択します。この権限を選択すると、他に必要な権限(repo)も付随して自動的に選択状態になります。

4. .npmrc を設定する

├ dist/
├ node_modules/
├ package.json
├ tsconfig.json
├ .gitignore
├ .npmrc
└ src/
  └ index.ts

上記の通り .npmrc を新規作成します。そして以下のように記載してください。

.npmrc

@harry-potter:registry=https://npm.pkg.github.com/harry-potter
//npm.pkg.github.com/:_authToken=ghp_acbdefghijklmnopqrstuvwxyz0123456789

_authToken には先の手順で生成した実際のトークンを設定してください。

5. npm publish する

npm publish を実行します。

npm publish

これでパッケージはパブリッシュされました。

GitHub のページを開くと、Packages のところが更新されていることがわかります。

Packages(画像の右下)

GitHub

6. パッケージを更新する場合

コード変更と合わせて package.jsonversion をあげてからビルドし npm publish します。

// 変更前
"version": "0.0.1",

// 変更後
"version": "0.0.2",

補足:万が一にも npmjs にパブリッシュしないために

これまでの方法だと .npmrc が存在しない場合には自動的に npmjs にパブリッシュする動きをします。

GitHub Packages 以外への誤ったパブリッシュを避けるためには package.json に以下の設定を加えておきましょう。

package.json

{
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/"
  }
}

パッケージを利用する

1. .npmrc を作成する

パッケージを利用したいリポジトリの中に、先ほど作成した .npmrc をコピー作成します。

2. インストールする

package.json に先ほど作成したパッケージ名とそのバージョンを指定してインストールします。

{
  "dependencies": {
    "@harry-potter/example-core": "0.0.1"
  }
}
npm i

3. 使用する

後は通常のパッケージと同様に利用するだけです。

import { sum } from '@harry-potter/example-core';
import type { Summable } from '@harry-potter/example-core';

const nums: Summable = [1, 2];
sum(nums); // 3

補足:.npmrc に利用するユーザについて

上記ではパッケージ利用者側の .npmrc にパッケージ開発者と同じものをコピペして使用しました。

この場合、パッケージ利用者もこのアクセストークンを利用することでパッケージを更新することが可能です。

利用者にパッケージ更新の権限を与えたくない場合は、別のアクセストークンを発行してそちらを利用者の .npmrc に適用するようにします。

その場合は read:packages を与えたアクセストークンを作成しましょう。

参考

Working with the npm registry

https://docs.github.com/ja/packages/working-with-a-github-packages-registry/working-with-the-npm-registry

パッケージのリポジトリをモノリポで作成している場合は以下の記事が参考になります。

https://dev.classmethod.jp/articles/github-packages-private/