npm.jsでPrivate Packageを運用するあれこれ
この記事はスクラップ「npm.jsでPrivate Packageを運用する時のあれこれ」の内容を修正, 加筆したものです。
前提
全体的に1からPrivate Packageを作るハンズオン的な内容になっています。
条件
- レジストリはnpm.jsを使用しています(よくあるGitHub Packagesではないので注意
- npm.jsの有料契約($7/月/人)が必要です。
- 諸々の取り扱いやすさからyarn(4系)をしています
- CommonJSです。
Native ESMにする方式は最後の方に書きます。(力尽きました
やりたいこと
$ npm install @ky-y./private-package
というように、組織内共通の「プライベートな」パッケージを、npm.jsレジストリで運用する。
結論
Private Package導入する側(アプリケーション側)はYarnのberryを用いると便利
NPM_TOKENの設定を美味しい感じに見たい場合は、#5, 使ってみるらへんをご参照ください。
基本手順
1, パッケージを作成する
$ mkdir private-library-0918 && cd private-library-0918
$ yarn init -2
厳密に言えば、パッケージ側はnpmでもYarn(Classic, Berry ...)でもなんでもいいんですが、せっかくなら導入する側と同じYarnの4系を使用します。
{
- "name": "private-library-0918",
+ "name": "@ky-y./private-library-0918",
+ "version": "0.0.1",
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
"packageManager": "yarn@4.5.0"
}
初期では、スコープがついていないのでスコープをつけます。自分の場合は@ky-y.
というスコープを所有しているので、そちらをつけます。
また、npmでパッケージを配信するにはバージョンが必須のため、初期バージョン0.0.1
をつけます。
main
とtypes
は、導入側から参照するファイルです。そのため、後述するdist内にビルドされたファイルを指定します。
yarnPath: .yarn/releases/yarn-4.5.0.cjs
+nodeLinker: node-modules
また、Yarnの設定ファイルである.yarnrc.yml
も初期ではnode_modules
を作成しない(Zero install)ようになっているので、node_modules
を作成するように設定を変更します。
2, TypeScriptの構築
$ yarn add -D typescript
$ npx tsc --init
{
"compilerOptions": {
"target": "ES2016",
"module": "CommonJS",
"outDir": "./dist",
"esModuleInterop": true,
"declaration": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": [
"src/**/*.ts"
]
}
tsconfig.json
の設定は上記のように変更しています。
3, 実装
あまり難しい実装はしません。
export { Hoge } from "./hoge";
export { Piyo } from "./piyo";
export class Hoge {
readonly input: string;
constructor(input: string) {
this.input = input;
}
response = (): string => {
return this.input;
};
output = (): void => {
console.log(this.input);
};
}
import { Hoge } from "./hoge";
export class Piyo {
readonly hoge: Hoge;
constructor(hoge: Hoge) {
this.hoge = hoge;
}
output = () => {
this.hoge.output();
};
response = (): string => {
return this.hoge.response();
};
}
ここまで実行した時に、以下のコマンドを実行してください。
$ npx tsc
実行完了後、dist
ディレクトリが以下のようになれば問題ないです。
4, 公開(限定公開)
$ npm publish --access=restricted
スコープがついたパッケージはデフォルトで限定公開になりますが、念のため明示的に指定します。
認証等が求められますので、いい感じに認証してください。
最後に以下のような表示になれば成功です。
...
Authenticate your account at:
https://www.npmjs.com/auth/cli/...
Press ENTER to open in the browser...
+ @ky-y./private-library-0918@0.0.1
npm.jsの公開したパッケージにアクセスした時に以下のようにPrivate
になっていればOKです。
きちんとPrivate Packageとして公開されています。
5, 使ってみる
適当にプロジェクトを作成してください。
$ mkdir usage-0918
$ cd usage-0918
$ yarn init -2
$ yarn add -D typescript ts-node
$ npx tsc --init
ここからがポイントです。
yarnPath: .yarn/releases/yarn-4.5.0.cjs
+nodeLinker: node-modules
+npmScopes:
+ ky-y.:
+ npmAlwaysAuth: true
+ npmAuthToken: ${NPM_TOKEN}
+ npmRegistryServer: "https://registry.npmjs.org"
npm.jsから、読み取り専用のNPM_TOKENを発行してあげてnpmAuthToken
に設定してください。
npmScopes
のky-y.
は皆さんのスコープに置き換えてください。
セキュリティ?ローカルだけでやるから問題ない!という場合は、npmAuthToken: "npm_..."
と書いてしまっても最悪大丈夫です。
セキュリティを気にする良い子の皆さんには付録に書いてある2通りいずれかの方法をお勧めします。
$ yarn add @ky-y./private-package-0918
上記コマンドを実行すると、先ほど公開(限定公開)したライブラリをインストール可能です。
(人によって、スコープや名称は違うと思うので適時調整してください。
あとは利用するだけですね。
import { Hoge, Piyo } from "@ky-y./private-library-0918";
const hoge1 = new Hoge("aiueo");
const hoge2 = new Piyo(hoge1);
hoge1.output();
console.log(hoge1.response(), hoge2.response());
console.log(hoge1.response() === hoge2.response());
$ ts-node test.ts
aiueo
aiueo aiueo
true
ここまでできれば完璧ペキ子ちゃんですね。
パッケージのアップデート
ライブラリ側
ローカル
$ npm version patch
$ npm publish
簡単ですね。
しかし、「お主!リリース前にGitにpushしろよ!」と怒られる場合があります。そういう時は以下のオプションをつけたコマンドに置換してください。
$ npm version patch --no-git-tag-version
$ npm publish
GitHub Actions
name: Publish Package to npmjs
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- name: Cache Dependencies
id: yarn_cache
uses: actions/cache@v4
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: Install Dependencies
if: steps.yarn_cache.outputs.cache-hit != 'true'
run: yarn install
- name: Publish Package to npmjs
run: |
npm run build
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
npm version patch
git push
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
事前にActionsのSecretにnpm.jsから吐き出した書き込み権限があるトークンを設定してください。
導入側
$ yarn up @ky-y./private-library-0918
付録:NPM_TOKENをいい感じに運用する
.envに直書き
NPM_TOKEN="npm_..."
.envを.gitignoreに設定すればいい感じですね。
1Passwordの秘密参照を使う
自分はこっちを使ってます。
NPM_TOKEN="op://Personal/~~~~~/credential"
op://Personal/~~~~~/credential
は、1PasswordにNPM_TOKENを登録後、下矢印をクリックし「秘密参照をコピーする」をクリックすると取得可能です。
alias op-run='op run --env-file=.env /bin/zsh'
導入側のプロジェクトディレクトリでop-run
とTerminalで実行すると、1Passwordの認証画面が開きます。
認証完了後、元の表示に戻っているようですが、NPM_TOKENには1Password内に登録された値が格納されています。チーム開発とかに便利ですね。
/Volumes/Projects/ky-y./usage-0918 $ op-run
/Volumes/Projects/ky-y./usage-0918 $
# ↑ op runのセッション中。NPM_TOKENが環境変数に格納されてる。
注意点としては、op runのセッション中でないとyarnの全てのコマンドが利用できません。
Discussion