以前、Tailwind CSSを使ったコンポーネントの設定を複数のプロジェクトで使いまわす方法を調べた。
GitリポジトリとしてGitLab.comを使っており、GitLabのパッケージレジストリにnpmパッケージを公開することで、公開範囲を絞ることができるため、その方法をメモ。
環境
Node.js v16.15.1, npm v8.11.0, Yarn v1.22.19。
OSはWindows 10 Pro 64bit 21H2、コマンドはGit 2.35.1.windows.2のGit Bashから実行して確認。
GitLabの設定
GitLab上でプライベートなプロジェクトを作成しておく。
パッケージレジストリの種類として、プロジェクトレベルとインスタンスレベルがある。今回はインスタンスレベルで設定する。
インスタンスレベルの場合、npmパッケージはスコープ付きにする必要がある。Gitプロジェクトが属するグループ名の先頭に @ を付与したものが、npmパッケージのスコープ名となる。
なお、実際のソースコードが書かれたGitプロジェクトと、npmパッケージを公開するGitプロジェクトは同じである必要はない。
パッケージ公開するNode.jsプロジェクトの設定
アクセストークンの発行
GitLab CI/CDによるパイプライン内ではなく、手動で実行する場合、パッケージレジストリとするGitプロジェクトにアクセス可能な、アクセストークンを発行する。アクセストークンのスコープは、 api のみでいい。
発行したトークンは、 .bashrc などで export NPM_TOKEN=... しておく。
package.json の変更
package.json の name を、 <スコープ名>/任意のパッケージ名 に変更する。
GitLabのグループ名が my-org 、パッケージ名を components とする場合、 @my-org/components 。 *1
また、 private が true であれば false にしておく。
.npmrc の変更
.npmrc に、以下の記述を追加。公開するGitLabプロジェクトのプロジェクトIDが必要となる。
<スコープ名>:registry=https://<GitLabドメイン>/api/v4/projects/<プロジェクトID>/packages/npm/
//<GitLabドメイン>/api/v4/projects/<プロジェクトID>/packages/npm/:_authToken=${NPM_TOKEN}
${NPM_TOKEN} には環境変数が設定される。GitLabドメインは、GitLab.comを使用している場合は gitlab.com 、オンプレミス環境であればそのドメインを設定する。
例として、GitLab.com上のGitプロジェクトで、グループ名が my-org , プロジェクトIDが 12345678 の場合、以下のようになる。
@my-org:registry=https://gitlab.com/api/v4/projects/12345678/packages/npm/
//gitlab.com/api/v4/projects/12345678/packages/npm/:_authToken=${NPM_TOKEN}
GitLab CI/CDのパイプライン経由で公開する場合
GitLab CI/CDのパイプライン経由でパッケージ公開を行う場合、CI/CD時の環境変数を利用するよう書き換えることも可能。
@my-org:registry=https://gitlab.com/api/v4/projects/12345678/packages/npm/
//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}
レジストリURLは、 @${CI_PROJECT_NAMESPACE}:registry=https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/ のようにも書き換えられそうだが、ローカルでうっかり npm publish したときに www.npmjs.com に向きそうなので、固定値で設定している。
公開処理の実行
npm publish --dry-run し、 Publishing to ... で表示されるURLが、指定したレジストリURL(この例では https://gitlab.com/api/v4/projects/12345678/packages/npm/ )となっていれば正しく設定できている。
npm publish を実行したら、ブラウザで公開先のGitLabプロジェクトのページを開き、左フレームの「パッケージとレジストリ」>「パッケージレジストリ」を開く。
指定したパッケージ名およびバージョンで、npmパッケージが登録されていれば成功。
パッケージを利用するNode.jsプロジェクトの設定
アクセストークンの発行
パッケージレジストリとするGitプロジェクトにアクセス可能な、アクセストークンを発行する。アクセストークンのスコープは、 read_api のみでいい。
また、スコープ api は read_api を含むので、パッケージ公開するNode.jsプロジェクトの設定を行っているのであれば流用可能。
.npmrc の変更
.npmrc に、以下の記述を追加。公開側との違いとして、 /project/<プロジェクトID> が不要となっている。
<スコープ名>:registry=https://<GitLabドメイン>/api/v4/packages/npm/
//gitlab.com/api/v4/packages/npm/:_authToken=${NPM_TOKEN}
例として、GitLab.com上のGitプロジェクトで、グループ名が my-org の場合、以下のようになる。
@my-org:registry=https://gitlab.com/api/v4/packages/npm/
//gitlab.com/api/v4/packages/npm/:_authToken=${NPM_TOKEN}
この設定が正しく行われていれば、普通に npm install できる。
Yarnを用いる場合
それぞれ npm publish および npm install で動作確認したが、プロジェクトのパッケージマネージャーとしてはYarn Classicを使っている。
それぞれ yarn publish とyarn add に置き換えられないか確認した。
yarn publishによるパッケージ公開
結論から言うと、まったく使い物にならなかったので、 npm publish を使い続けることとした。
yarn publish はデフォルトでは対話型だが、 yarn publish -non-interactive で非対話型で実行できるものの、いろいろと問題があった。
- パッケージに含めるファイルを調整したときに、確認のため
npm pack --dry-runを使うが、npm packに該当するコマンドがYarnにない- issueはあるが放置
- Yarn v2以降であれば追加された模様
package.jsonのfilesで指定していないファイルがパッケージに含まれる
yarn publishの改善のissueもあるが、改善されそうもないので、 npm publish を使う。
yarn addによるパッケージ追加
yarn add を実行すると以下のエラーが発生する。
error An unexpected error occurred: "https://
ドメイン>/api/v4/projects/<プロジェクトID>/packages/npm/<スコープ名>/<パッケージ名>/-/<スコープ名>/<パッケージ名>-<バージョン>.tgz: Request failed \"404 Not Found\"".
同じ問題の質問が、GitLabフォーラムにあった。
コメントにあるように、 .npmrc に //<GitLabドメイン>/api/v4/projects/:_authToken=${NPM_TOKEN} を追加すると成功するようになった。
先の例に追加すると、以下のようになる。
@my-org:registry=https://gitlab.com/api/v4/packages/npm/
//gitlab.com/api/v4/packages/npm/:_authToken=${NPM_TOKEN}
//gitlab.com/api/v4/projects/:_authToken=${NPM_TOKEN}
振り返り
基本的には公式ドキュメント通りに進めるだけだったが、Yarnを使う場合にはもろもろ手直しが必要だった。
特にpublishの挙動の違いにはまいった、なぜうまく動かないのかもよくわからない。npm用の設定ファイルが読み込まれていないのか?
ただ、掘り下げるのも時間の無駄なので、調査はしていない。
あと、そろそろYarnもmodernに乗り換えないとかなぁ。
*1:グループ名は example にしようと思ったが、GitLab.com上に存在していた