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.jsonrepositorypublishConfigを追加する必要があります。

    {
      "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を使ったライブラリ管理は、知っておくといろいろと捗りそうです。

    参考

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark