業務でNode.jsアプリケーションをデプロイする際に、nexeを使用する機会がありました。しかしnexeでパッケージングしたアプリケーションを実行しようとすると、「Cannot find module」というエラーが発生し、起動できない状況に直面しました。
エラーの原因や対処法に関する具体的な記事が見つからなかったため、今回その解決方法を記事としてまとめることにしました。同じ問題で困っている方の参考になれば幸いです。
※結論から言うと根本解決にはなっていないですが、アプリケーションに影響ないレベルのため措置としています。
nexeとは
nexeとは、Node.jsのライブラリで、Node.jsのruntimeを含めた形でバイナリファイルにバンドルすることができます。Linux,Windows,macOSなどのプラットフォーム別にバイナリファイルを提供可能です。exeファイル(Windowsの場合)をサーバーに配置するだけで済み、本番環境でのアプリケーションの構築やアプリケーションの更新作業が楽になるため、業務でnexeを使ってみました。
実行環境
- Windows
- Node.js v20.15.1
- npm 10.8.1
- nexe 4.0.0-rc.6
事象について
nexeでは、以下のようにアプリケーションをパッケージングします。
nexe --build -i ./dist/index.js --resource ./dist/public/**/* -t windows-x64-20.15.1 -o ../bin/MyApp.exe
パッケージングも問題なく成功し、いざMyApp.exe
を実行してみると
node:internal/modules/cjs/loader
throw err;
^
Error: Cannot find module 'mkdirp'
Require stack:
・・・
code: 'MODULE_NOT_FOUND',
・・・
エラーとなり、思ったように動いてくれません。
原因調査
エラーメッセージに表示されたライブラリは、installした覚えがありませんでしたが、package-lock.json
を見ると、依存ライブラリとしてinstallしていたようです。node_modules
配下のフォルダからもinstallした形跡を確認できました。
バージョン等の情報は異なりますが、GitHubで類似のディスカッションが複数ありました。
根本的な原因はよくわからないですが、ライブラリにバグがあり、node_modules内のライブラリをうまくパッケージングしてくれないことがあるようです。
措置策
今回はnexeでパッケージング時に「Cannot find module」となるライブラリを明示的にresource
で指定する対応をしました。
nexe --build -i ./dist/index.js --resource ./dist/public/**/* --resource ./node_modules/mkdirp/**/* --resource (他にもパッケージングから漏れたライブラリを指定) -t windows-x64-20.15.1 -o ../bin/MyApp.exe
上記でパッケージングしたMyApp.exe
は問題なく起動することを確認できました。
対応する過程で、エラーメッセージに表示されたライブラリを含めてパッケージングすると、別のライブラリがエラーメッセージに表示されたので、エラーメッセージが表示されなくなるまで追加しました。
パッケージング漏れのライブラリの探索が面倒だったので、--resource ./node_modules/**/*
としたのですが、node_modules
全体を含めてパッケージングすると、パッケージング後のexeのファイルサイズが2倍近くまで膨れ上がってしまいました。流石に2倍は膨れすぎだと判断し、地道にライブラリを指定しました。
合計4つ程度のライブラリを指定することで収まり、ファイルサイズは1.1倍増位となりました。ファイルサイズ増加のデメリットがありますが、アプリケーションには影響なく動作したので今回はこの措置をとりました。
最後に
今回はnexeでパッケージング漏れを起こすライブラリを明示的にresource
で指定する対応をしました。
また、nexeのGitHubのactivityを見ると活動はあまり活発でないので、今後はnexe以外の選択肢も検討した方がよさそうです。
例えば、Node.jsはv20からSingle executable applicationsを試験的に標準機能として提供し、v21以降は正式リリースとなっています。標準機能で提供があるなら、あえてライブラリに頼らず標準で済ませたくなりますね。