最近良くバイナリファイルを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回実行すると成功するという不思議な状況になりました。
さらに、この失敗するモジュールを読み込んだプロジェクトで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
を試したり、親子関係の依存にならないようにしてみたり、いろいろ試して見ましたがダメでした・・・。
対策
試行錯誤した結果、下記のように対策をとることになりました。
"postinstall": "npm update && node install.js"
postinstall
の実行のさいに依存モジュールの解決が終わってないなら、強制的にインストールすれば良いということでnpm update
を実行してやることにしました。
どう考えても悪手な臭いがぷんぷんします。
さいごに
いったい、これはどうすれば良かったんでしょうか?
初めてのpostinstall
でガンはまりして試行錯誤して、この結論に行き着きましたが、世の中のpostinstall
を使ってる人たちはどうしているんでしょうね。
そもそも組み方が悪かった疑惑もあるのですが、どうすれば良いのか上手いやり方をご存知の方がいましたら教えてください。