Nxで作成したReact ComponentをGitHub Package Registoryで公開する
社内利用などを前提としており、Publicに配布したくないライブラリを作る場合にGitHubのPackage Registoryは有力な公開先の1つです。そして、「1つのデザインシステムをベースに、複数のサービス・アプリ […]
目次
社内利用などを前提としており、Publicに配布したくないライブラリを作る場合にGitHubのPackage Registoryは有力な公開先の1つです。そして、「1つのデザインシステムをベースに、複数のサービス・アプリ向けの拡張ライブラリを作る」というユースケースに対しては、NxやLernaなどを用いたmonorepoでのソース管理が効率的になることがあります。
この2つを組み合わせたものを、仕事でやる必要が出てきそうだったので試行錯誤していました。
セットアップ
まずはNxでセットアップから
$ npx create-nx-workspace
nx-gh-registory --preset react
スタイリングの方法などいろいろ聞かれますので、作りたいものの要件に合わせて回答しておきましょう。
Pacakgeの作成
続いてライブラリを作ります。--publishable
をつける必要があることと、importPath
で公開するライブラリの名前を設定する必要がある点に注意しましょう。
% yarn nx g @nrwl/react:library --name=ui --publishable --importPath @hideokamoto/nx-react-ui-example
% yarn nx g @nrwl/react:library --name=greeding --publishable --importPath @hideokamoto/nx-react-greeding-example
各package.json
にregistroy情報を追加する
GitHubのPackage Registoryに公開する場合は、追加した各Packageのpackage.json
にrepository
とpublishConfig
を追加する必要があります。
{
"name": "@hideokamoto/nx-react-greeding-example",
"version": "2.0.0",
"repository": {
"type": "git",
"url": "https://github.com/hideokamoto/nx-react-github-registory"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com/@hideokamoto"
}
}
repository
にはGitHubリポジトリのURLを、publishConfig.registory
にはhttps://npm.pkg.github.com/@USERNAME
を指定しましょう。
.npmrcでレジストリの設定を行う
公開したいライブラリのScopeだけGitHubのレジストリを使うように設定しておきましょう。
//npm.pkg.github.com/:_authToken=${GITHUB_ACCESS_TOKEN}
@hideokamoto:registry=https://npm.pkg.github.com
registry=https://registry.npmjs.org
always-auth=false
まとめてnpm publishするスクリプト
最後にnpm publish
で公開します。参考にした海外のブログ記事にあるスクリプトが「更新されたものだけ対象にリリースする」挙動をしていましたので、とりあえず今はこれを利用しています。
#!/usr/bin/env bash
set -o errexit -o noclobber -o nounset -o pipefail
# This script uses the parent version as the version to publish a library with
getBuildType() {
local release_type="minor"
if [[ "$1" == *"BREAKING CHANGE"* || "$1" == *"!:"* ]]; then
release_type="major"
elif [[ "$1" == *"feat"* ]]; then
release_type="minor"
elif [[ "$1" == *"fix"* || "$1" == *"docs"* || "$1" == *"chore"* ]]; then
release_type="patch"
fi
echo "$release_type"
}
PARENT_DIR="$PWD"
ROOT_DIR="."
echo "Removing Dist"
rm -rf "${ROOT_DIR:?}/dist"
COMMIT_MESSAGE="$(git log -1 --pretty=format:"%s")"
RELEASE_TYPE=${1:-$(getBuildType "$COMMIT_MESSAGE")}
DRY_RUN=${DRY_RUN:-"False"}
AFFECTED=$(node node_modules/.bin/nx affected:libs --plain --base=origin/master~1)
if [ "$AFFECTED" != "" ]; then
cd "$PARENT_DIR"
echo "Copy Environment Files"
while IFS= read -r -d ' lib; do
echo "Setting version for $lib"
cd "$PARENT_DIR"
cd "$ROOT_DIR/libs/${lib/-//}"
npm version "$RELEASE_TYPE" -f -m "chore: $RELEASE_TYPE"
echo "Building $lib"
cd "$PARENT_DIR"
npm run build "$lib" -- --with-deps
wait
done <<<"$AFFECTED " # leave space on end to generate correct output
cd "$PARENT_DIR"
git add ./
git commit -m "chore: $RELEASE_TYPE"
while IFS= read -r -d ' lib; do
if [ "$DRY_RUN" == "False" ]; then
echo "Publishing $lib"
npm publish "$ROOT_DIR/dist/libs/${lib/-//}" # --access=public
else
echo "Dry Run, not publishing $lib"
fi
wait
done <<<"$AFFECTED " # leave space on end to generate correct output
else
echo "No Libraries to publish"
fi
元のスクリプトではnpm version
の結果がcommitされていない状態でしたので、git commit
するように少し手を入れています。
このあたりはSemantic Release系のライブラリを使ったり、Nxのプラグイン化したりすることである程度柔軟な使い方ができるのではないかなと思います。
公開の確認
あとはGitHubにアクセスして公開されているかを確認しておきましょう。
注意点
README.mdはプロジェクトルートのものが採用される
これはNxのビルド設定次第みたいですが、デフォルトだとプロジェクトルートにあるREADME.mdがビルドパッケージにバンドルされます。なのでライブラリの使い方などは、libs/PACKAGE/README.md
ではなくREADME.md
に記述しましょう。
namespaceはGitHubのUsername / Organization nameのみ
基本的に「そのリポジトリのあるUsername / Organization name」を@NAMESPACE
に指定します。
そのため別のnamespaceを利用したい場合は、organizationを作成してリポジトリをtransferする必要がありそうです。
そのほか
やってることは個別のnpm packageをReleaseしているだけですので、理論上NxでAngular / Vue / React / Web Componentをまとめて管理することも可能です。
ですのでIonic Frameworkのように「Web Componentをベースに、Angular / Vue / Reactで使うライブラリもリリースする」という作り方をNxで作ったmonorepoでやることは可能かなと思います。
GitHubのReleaseやCHANGELOG.mdでどのライブラリが更新されたかをわかりやすくする部分が今後の検討事項かなとは思いますが、Nxを使ったライブラリ管理は、知っておくといろいろと捗りそうです。