この記事では最近自分が使ってるnpm publishでのモジュール公開のパターンについて紹介します。

npm publishで公開する先は2パターンあるので、以下の2パターンについて書きます。

  • Public
  • Private(scoped packages)

また使用するnpmはv2.7.0以上が対象です。


npm publish

先に結論的な今使ってるものを貼っておきます。 zshの関数とaliasですが、基本的にただのコマンドの組み合わせなので大体の環境で動かせる気がします。

(今後gistの方を更新するかもしれないので、記事中に書かれてるものよりgistの方が最新です)

大まかな流れは

事前準備 -> semverでコミット -> push

という感じになります。

使い方

  • npm-patch
  • npm-minor
  • npm-major
  • private-npm-patch
  • private-npm-minor
  • private-npm-major

PublicとPrivateの2種類のコマンドを後ほど話す理由で分けてますが、基本的にはpatch, minor, majorの3つのコマンドです。

見てわかるように、Semantic versioningのpatch, minor, majorに対応しています。

実行すると、依存のチェックやテスト、version変更のコミット、git tag、ビルドが必要ならnpm run build、最後にnpm publishします

function _confirm-npm(){
  echo -n "npm publish to \033[036m$1\033[0m. OK? "
  read INPUT
  echo "\033[31m=>\033[0m \033[036m$1\033[0m"
}
alias npm-patch='_confirm-npm "Public" && pre-version && npm version patch && post-version'
alias npm-minor='_confirm-npm "Public" && pre-version && npm version minor && post-version'
alias npm-major='_confirm-npm "Public" && pre-version && npm version major && post-version'
alias private-npm-patch='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version patch && post-version'
alias private-npm-minor='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version minor && post-version'
alias private-npm-major='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version major && post-version'
alias pre-version='git diff --exit-code && npm prune && npm install -q && npm test'
alias post-version='npm run --if-present build && git diff --exit-code && git push && git push --tags && npm publish'

実行されるコマンドの流れを見ていくといかのような感じになってます。

  • diffがないか
    • git diff --exit-code
  • pacakge.jsonに書いてない依存モジュールを使ってたりしないか
  • テストがちゃんと通るか
    • npm prune && npm install -q && npm test
  • semverでpackage.jsonの変更とgit tagを貼る
    • npm version <patch|minor|major>
  • ビルドスクリプトが定義されてるならビルドする
    • npm run --if-present build
    • --if-present で "build" がないなら無視できる
    • npm v2.7.0から入った機能なのでnpmが古いとだめ。
  • ビルドファイルがgitで管理されないか
    • npm run --if-present build && git diff --exit-code
  • git push
  • npm publish
    • git push && git push --tags && npm publish

npm-patch を叩くと色々チェックして、patchバージョンを上げてコミットしたものをgit pushとnpm publishしてくれる感じですね。

Privateへの公開

npm publishはパッケージがScoped packagesであるならばPrivateへ、そうでないならPublic(npmjs.com)への公開がデフォルトの挙動になっています。

具体的にはnpm publishすると以下のようなもの以外の時はPublicへ公開する挙動になります。

  1. private : true となってる
    1. package.jsonのprivate設定
  2. Scoped packages である
    1. Scoped packagesはpacakge nameが@から始まるもの
  3. publishConfigでpublish先を設定されてる
    1. package.jsonのpublishConfig設定

上記のどれかに該当する場合は、正しく設定されていればPrivateへ公開され、また設定が一部おかしかった場合もPrivateへリクエストを投げるので、Publicには漏れなくなります。

理想的には、package.jsonを作るときに最初からScoped packagesとして作ると間違ってPublicに公開されることはなくなるので安全です。 package.jsonを作るときに

npm init mypackage —scope=myorg
# @myorg/mypackage ができる

ですが、どちらにしてもnpmの設定かpackage.jsonの変更が必要で、それを忘れてnpm publishしてしまうことがありえるのと、そもそもPublicとPrivateが設定情報というコンテキストで自動で切り替わるのが怖かったのでコマンドとして分けるようしました。

  • npmjsにPublic公開したい時
    • npm-<patch|minor|major> を叩く
  • Private regitoryに公開したい時
    • private-npm-<patch|minor|major> を叩く

というCLIの段階で分かれてると意識しやすくなるので、npm publishを内部でrelease-itのようなツールを使ってなければ大分事故が少なくなりそうです。

alias private-npm-patch='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version patch && post-version'
alias private-npm-minor='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version minor && post-version'
alias private-npm-major='_confirm-npm "Private" && scoped-modules-checker && pre-version && npm version major && post-version'

実際に見てみると最初にscoped-modules-checkerでそれがscoped packagesであるかをチェックするのが入ってるだけで、あとはnpm-patchなどと同じですね。

今回はチェックするコマンドの組み合わせでやっていますが、scoped packagesじゃないとpublishできないprivate-npm-publishというnpm publishのラッパーコマンドもあります。

npm publishに対するグローバルなホックは書けないので、こういうアプローチになる感じです。


そもそも「なぜそこまでPrivateのものを間違って公開した時のことを気にするの? npm unpublish -f すればいいのでは?」と思うかもしれませんが、以下のブログで書かれているように現在(2015-04-09)のnpmは一度上げるとそれを完全に消すことはできない仕組みなってると書いてあります。


あと細かな工夫として npm-patch の方はPublicで公開される可能性があるので、最初に確認を出すようにしてます。(ただEnter押せばいいだけ)

npm-patch

間違ってEnterおしても、installやtestなどが走るのでその間にCtrl+Cとかでキャンセルできるので数秒は猶予があります。

後はpackage.jsonのfilesとかをチェックしたい感じですが、基本的にコマンドの組み合わせなのでそういうコマンド作っていく感じになりそう。

おわり

  • npm version publish alias について紹介した
  • PublicとPrivateでnpm publish叩くのは同じだけどコマンドを分けた