猫でもわかるWebプログラミング

試行錯誤しながらエンジニア(プログラマー)として働く猫のブログ。技術的な話や、働き方の話、読書録とか、試行錯誤している日常の話。

Electron + Webpack を使っていて Can't resolve iconv.node

f:id:yoshiki_utakata:20181004212834j:plain

Can't resolve iconv.node

Electron + Webpack の構成で開発していて、 active-win *1 というライブラリをつかってPCのモニタリングをするツールを作ろうとしたいたら、こんなエラーに遭遇した。

WARNING in ./node_modules/iconv/build/Release/iconv.node 1:0
Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
 @ ./node_modules/iconv/lib/iconv.js 27:13-51
 @ ./node_modules/ref-wchar-napi/index.js
 @ ./node_modules/active-win/lib/windows.js
 @ ./node_modules/active-win/index.js
 @ ./src/batch/updater.ts
 @ ./src/index.tsx

ERROR in ./node_modules/iconv/lib/iconv.js
Module not found: Error: Can't resolve '../build/Debug/iconv.node' in '/Users/yoshiyuki_sakamoto/tele-san/node_modules/iconv/lib'
 @ ./node_modules/iconv/lib/iconv.js 31:13-49
 @ ./node_modules/ref-wchar-napi/index.js
 @ ./node_modules/active-win/lib/windows.js
 @ ./node_modules/active-win/index.js
 @ ./src/batch/updater.ts
 @ ./src/index.tsx

エラーを調べてみる

エラー内容を見ると、../build/Debug/iconv.node がないというエラーだ。

エラーメッセージでググってみると、いくつかそれっぽいものがヒットする。

node_modules/iconvnode-gyp rebuild しろというものだ。しかしこれでは解決しなかった。

実際に node_modules/iconv/build/Debug/iconv.node を調べてみると無い。そして node-gyp rebuild してもこのファイルは生成されない。

コードをちょっと見てみる

エラーのスタックトレースを見てコードを追ってみると、該当部分はこうなっていた。

var bindings;
try {
  bindings = require('../build/Release/iconv.node');
}
catch (e) {
  if (e.code !== 'MODULE_NOT_FOUND') throw e;
  bindings = require('../build/Debug/iconv.node');
}

エラーが出ている部分は bindings = require('../build/Debug/iconv.node'); の部分だが、そもそも bindings = require('../build/Release/iconv.node'); でエラーが投げられているのが問題であった。

そこで、 node_modules/iconv/build/Release/iconv.node を見て見ると、こっちは存在している。が、エラーになっている。何故だろうか。

Webpack の設定が足りていなかった

原因は Webpack の設定でした。 Webpack の対象ファイルに build/Release/iconv.node が入っていなかったので、ビルドの成果物に iconv.node が含まれていませんでした。

そこで Webpack の設定を追加しました。全体像は以下です。

重要な点は

  • module.rules に node を追加し、resolve に .node を追加
  • externals に "../build/Debug/iconv.node" を追加

の2点です。

module.rules に node を追加

node-loader をインストールします。

npm install node-loader

resolve に .node を追加し、iconv.node を webpack の対象ファイルとしたうえで、 rules に .node の場合 node-loader を設定するようにします。

webpack は指定されたファイルを全部 bundle ディレクトリ以下(ビルド成果物)にまとめてくれるのですが、ここの条件に入っていないとビルド成果物に含まれなくなってしまうので、 iconv.node が無いというエラーになるのです。

iconv.node が bundle 後のファイルに含まれればいいのですが、多分ビルドとかは不要なので、 node-loadler じゃなくて file-loader でも動くかもしれません。

この設定を書と、bundle ディレクトリ直下に <ハッシュっぽい文字列>.node というファイルが増え、これがもとの iconv.node と同じサイズなので、名前が変わっただけで同じファイルのようです。ちゃんと bundle されているっぽい。

externals に "../build/Debug/iconv.node" を追加

externals とは、webpack の管轄範囲外のファイルを書く場所です。HTMLの