Posted at

bin-wrapperでバイナリを取り込むときにpostinstallにハマった話

More than 3 years have passed since last update.

最近良くバイナリファイルをbin-wrapperでラップして、npmプロジェクトに簡単に取り込めるようにしています。

* https://github.com/k-kinzal/scala-bin

* https://github.com/k-kinzal/sbt-bin

* https://github.com/k-kinzal/scalajs-standalone-bin

このときにbin-wrapperでラップしたバイナリに依存する、bin-wrapperでラップしたバイナリを作成すると、何故か1回目のnpm installに失敗して、2回実行すると成功するという不思議な状況になりました。

image

さらに、この失敗するモジュールを読み込んだプロジェクトでnpm installすると、インストール順序が狂い出すという困った事態になりました。

意味わかんない。


インストールに失敗したときの階層

仕方ないので、インストールして失敗したときにnode_modulesの階層構造を調べて見ました。

A

`-B

C

`-B

と言う構造のAモジュールにCモジュールをインストールしたときに

A

`-B
`-C

という構造になります。

この構造でBモジュールをインストールし終わった後に、Cモジュールのpostinstallが実行されることを期待したいのですが、実際にはBモジュールのインストールが終わる前にCモジュールのpostinstallが動いてしまいBモジュールの依存モジュールが見つからずにCannot find moduleとエラーが発生してしまいます。

インストール前にpostinstallが動いて困るなら、失敗した場合は遅延してリトライすればいけるのでは?と考えて試してみましたが上手く行きませんでした。

他にもnode shrinkwrapを試したり、親子関係の依存にならないようにしてみたり、いろいろ試して見ましたがダメでした・・・。


対策

試行錯誤した結果、下記のように対策をとることになりました。


package.json

"postinstall": "npm update && node install.js"


postinstallの実行のさいに依存モジュールの解決が終わってないなら、強制的にインストールすれば良いということでnpm updateを実行してやることにしました。

どう考えても悪手な臭いがぷんぷんします。


さいごに

いったい、これはどうすれば良かったんでしょうか?

初めてのpostinstallでガンはまりして試行錯誤して、この結論に行き着きましたが、世の中のpostinstallを使ってる人たちはどうしているんでしょうね。

そもそも組み方が悪かった疑惑もあるのですが、どうすれば良いのか上手いやり方をご存知の方がいましたら教えてください。