やってみたこと
node.jsのアプリをいくつか書いていたら、共通の処理が出てきたのでライブラリ化したくなった。
でもあれやこれや…な理由でパブリックには公開できなかった。
そこでnpmのリポジトリには公開せず、プライベートなgitリポジトリからnpm i git+https://<git-repo>
としてインポートすることにした。
npm prepublish の現状と今後どう変わっていくかという記事でnpm scriptsが実行される順序がまとめられていたので参考にしていたのだが、「publishされていないパッケージをgitのリポジトリから直接取ってきたらどうなんねん?」という疑問が湧いてきたので調べてみた。
検証環境
とりあえずnpm 5系と6系のふたつだけ調べました。
検証に使用したPCはmacOS Mojaveの入ったMacBook Proです。
1つ目
* node v8.11.4
* npm 5.6.0
2つ目
* node v8.12.0
* npm 6.4.1
検証方法
まずは下のようなpackage.jsonを用意する。scripts以外は基本的にnpm init -y
で吐き出しただけ。
{
"name": "npm-script-timings",
"description": "This project is used to check timings when each npm scripts run.",
"version": "1.0.0",
"keywords": [],
"license": "ISC",
"main": "index.js",
"scripts": {
"prepublish": "echo \"##### prepublish #####\"",
"prepare": "echo \"##### prepare #####\"",
"prepublishOnly": "echo \"##### prepublishOnly #####\"",
"prepack": "echo \"##### prepack #####\"",
"pack": "echo \"##### pack #####\"",
"postpack": "echo \"##### postpack #####\"",
"publish": "echo \"##### publish #####\"",
"postpublish": "echo \"##### postpublish #####\"",
"preinstall": "echo \"##### preinstall #####\"",
"install": "echo \"##### install #####\"",
"postinstall": "echo \"##### postinstall #####\"",
"preuninstall": "echo \"##### preuninstall #####\"",
"uninstall": "echo \"##### uninstall #####\"",
"postuninstall": "echo \"##### postuninstall #####\"",
"preversion": "echo \"##### preversion #####\"",
"version": "echo \"##### version #####\"",
"postversion": "echo \"##### postversion #####\"",
"pretest": "echo \"##### pretest #####\"",
"test": "echo \"##### test #####\"",
"posttest": "echo \"##### posttest #####\"",
"prestop": "echo \"##### prestop #####\"",
"stop": "echo \"##### stop #####\"",
"poststop": "echo \"##### poststop #####\"",
"prestart": "echo \"##### prestart #####\"",
"start": "echo \"##### start #####\"",
"poststart": "echo \"##### poststart #####\"",
"prerestart": "echo \"##### prerestart #####*\"",
"restart": "echo \"##### restart #####\"",
"postrestart": "echo \"##### postrestart #####\"",
"preshrinkwrap": "echo \"##### preshrinkwrap #####\"",
"shrinkwrap": "echo \"##### shrinkwrap #####\"",
"postshrinkwrap": "echo \"##### postshrinkwrap #####\""
}
}
このpackage.jsonをプライベートgitリポジトリにpushし、別プロジェクトからnpm i git+https://<git-repo>.git
したときのコンソールを見てみる。
今回はこのプロジェクトをnpm-script-timings
という名前のリポジトリにして、下のようなディレクトリ構成を取って確認してみた。別プロジェクトと言いながらサブディレクトリに含めてしまっているのは特に意味はありません。
npm-script-timings
├── package-lock.json
├── package.json # 上記のpackage.json
└── another-project # npm-script-timingsをインストールするプロジェクト
結果
パス中に登場してしまっている以下の名前は置換しています。
- ホームディレクトリ -> $HOME
- gitリポジトリのURL -> $GIT_REPO
npm 5.6.0の場合
インストール対象のスクリプトは、prepack -> postpack -> preinstall -> install -> postinstall
の順で動作するようです。
> npm-script-timings@1.0.0 prepack $HOME/.npm/_cacache/tmp/git-clone-d3d05fce
> echo "##### prepack #####"
##### prepack #####
> npm-script-timings@1.0.0 postpack $HOME/.npm/_cacache/tmp/git-clone-d3d05fce
> echo "##### postpack #####"
##### postpack #####
> npm-script-timings@1.0.0 preinstall $HOME/.ghq/$GIT_REPO/another-project/node_modules/npm-script-timings
> echo "##### preinstall #####"
##### preinstall #####
> npm-script-timings@1.0.0 install $HOME/.ghq/$GIT_REPO/another-project/node_modules/npm-script-timings
> echo "##### install #####"
##### install #####
> npm-script-timings@1.0.0 postinstall $HOME/.ghq/$GIT_REPO/another-project/node_modules/npm-script-timings
> echo "##### postinstall #####"
##### postinstall #####
added 1 package in 7.137s
npm 6.4.1の場合
基本的な動作はnpm 5.6.0
の場合と同じようですが、なぜかprepack
とpostpack
が2回ずつ走っています。
そこまで問題にはならない気もしますが、意図した動作ではなさそう?
> npm-script-timings@1.0.0 prepack $HOME/.npm/_cacache/tmp/git-clone-8b6cee0a
> echo "##### prepack #####"
##### prepack #####
> npm-script-timings@1.0.0 postpack $HOME/.npm/_cacache/tmp/git-clone-8b6cee0a
> echo "##### postpack #####"
##### postpack #####
> npm-script-timings@1.0.0 prepack $HOME/.npm/_cacache/tmp/git-clone-79212f62
> echo "##### prepack #####"
##### prepack #####
> npm-script-timings@1.0.0 postpack $HOME/.npm/_cacache/tmp/git-clone-79212f62
> echo "##### postpack #####"
##### postpack #####
> npm-script-timings@1.0.0 preinstall $HOME/.ghq/$GIT_REPO/npm-script-timings/another-project/node_modules/npm-script-timings
> echo "##### preinstall #####"
##### preinstall #####
> npm-script-timings@1.0.0 install $HOME/.ghq/$GIT_REPO/npm-script-timings/another-project/node_modules/npm-script-timings
> echo "##### install #####"
##### install #####
> npm-script-timings@1.0.0 postinstall $HOME/.ghq/$GIT_REPO/npm-script-timings/another-project/node_modules/npm-script-timings
> echo "##### postinstall #####"
##### postinstall #####
added 1 package and audited 1 package in 12.331s
found 0 vulnerabilities
まとめ
npmリポジトリから取得するときと違って、gitリポジトリから直接取得しようとしたときにはnpm prepack
とnpm postpack
が追加で動作するようです。
npmリポジトリに登録をしないときにはnpm publish
をするタイミングがないので代わりにnpm pack
が行われる、というイメージでしょうか。
おまけ
TypeScript で作ったパッケージを TravisCI で npm に公開するときの Tipsでも述べられてる.gitignore
と.npmignore
の動作に気付かずに同じハマり方しました…。