npm-version($ npm version [major|minor|patch|...]
)は「package.jsonのバージョンを上げてGitのコミットとタグを追加する」というコマンドですが、pre/postフックと組み合わせると結構いろいろなことができます。
テスト・ビルド・デプロイを絡めて、新しいバージョンのリリース自動化にも使えます。
npm-scriptsのドキュメントだと、"perversion"と"version"の説明がどちらも「パッケージをバージョンアップする前」に実行されるとしか書かれておらず、いまいち使い分けがわからなかったのですが、npm-versionのページには詳細が載っていました。
処理の流れ
$ npm version [major|minor|patch|...]
を実行すると、このような順で処理が走ります。
- Gitのワーキングディレクトリがクリーンになってるか確認する
- "preversion"のスクリプトを実行する
- package.jsonのバージョンを上げる
- "version"のスクリプトを実行する
- Gitコミット作成&タグ追加する
- "postversion"のスクリプトを実行する
太字(1, 3, 5)が本来のnpm version
の処理で、npm-scriptsに何も定義していなければ1, 3, 5だけが実行されます。"preversion", "version", "postversion"を定義すると、それぞれ2, 4, 6のタイミングでスクリプトが走ります。
特に"version"スクリプトは、package.json更新の後、コミットの前に実行されるので、「バージョン番号付きのファイルを出力する」といったビルドタスクは、pre/postフックではなく、"version"に定義する必要があります。
"version"スクリプトは、本来のnpm version
の処理を上書きするわけではありません。
一方、"preversion"はバージョンを上げる前の状態で実行されます。
サンプル
公式ドキュメントのサンプルが結構実践的な内容になってました。
"scripts": {
"preversion": "npm test",
"version": "npm run build && git add -A dist",
"postversion": "git push && git push --tags && rm -rf build/temp"
}
- ワーキングディレクトリがクリーンじゃないときは、何もしない
- テストが通らなかったら、package.jsonは更新しない
- ビルドは新しいバージョン番号を参照して実行する
- コミットにビルドで生成したファイルも追加する
- 正常に完了したら、リモートにプッシュして一時ファイルを削除する
このように、実行条件や順序が大事なリリース処理も、"preversion", "version", "postversion"のタイミングを理解すると綺麗に定義することができます。
まとめ
各スクリプトはこのように使い分けるのが良さそうです。
-
preversion
- package.jsonを更新する前に完了させたいこと(テストなど)
-
version
- 新しいバージョンとして実行し、リリースのコミットに含めたいこと(ビルド、CHANGELOGの生成など)
-
postversion
- 正常に完了した後に実行したいこと(リリース、一時ファイル削除など)