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/iconv
で node-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の