経緯
ReactでchromeのExtensionを開発していた時のこと。
とあるライブラリを使い始めたあたりから唐突にビルドが通らなくなりました。
今回は一旦エラーを消す方法について調べたので書き記しておきます。
エラー内容
ERROR in ~~
Module not found: Error: Can't resolve 'http' in ~~
上記の他にも tls やら fs やらも見つからんとエラー。
一個一個インストールするのかーめんどくさいなーと思いながら、なんかおかしいなという思いが湧き出てきてなんとなく調べてみました。
エラー原因
クライアントサイド用のビルドをするときに、サーバーサイド用のライブラリが含まれていると発生するようです。
webpackではデフォルトのビルドターゲットがクライアント用(web)になっており、サーバーサイド(多分SSRとか?その他でwebpackを使ってビルドする用途がわからない)であればtargetをnodeにしてあげればビルドできるようになるはずです。
対応策
How to Polyfill node core modules in webpack 5.
上記の記事を参考にしました。
やること
- パッケージ群のインストール
- webpack.config.jsにaliasの設定
- クライアントサイドで使用できないcoreようモジュールを無効にする
まずcore(サーバーサイド)用のライブラリを、クライアントサイドで使えるライブラリにaliasとしてマッピングするとともに対応したライブラリをインストールしてあげるって感じです。
パッケージ群のインストール
対応策の項で紹介したリンクのさらに先にあるサンプルから、ワンライナーでインストールできるように準備しておいたので褒めて欲しい気持ち。
$ yarn add -E -D assert buffer console-browserify constants-browserify crypto-browserify domain-browser events stream-http https-browserify os-browserify path-browserify punycode process querystring-es3 stream-browserify readable-stream readable-stream readable-stream readable-stream readable-stream string_decoder util timers-browserify tty-browserify url util vm-browserify browserify-zlib
※ ただし可読性は悪い
yarnを使っていますが、npmの人は適宜書き換えてください。
coreモジュールをクライアント用モジュールにマッピング
coreモジュールとして認識、ロードされてしまうパッケージ群をクライアントサイドで使用できるパッケージ群にマッピングするためのaliasを設定します。
webpack.config.jsに以下の記述を追加してください。
resolve: {
alias: {
assert: "assert",
buffer: "buffer",
console: "console-browserify",
constants: "constants-browserify",
crypto: "crypto-browserify",
domain: "domain-browser",
events: "events",
http: "stream-http",
https: "https-browserify",
os: "os-browserify/browser",
path: "path-browserify",
punycode: "punycode",
process: "process/browser",
querystring: "querystring-es3",
stream: "stream-browserify",
_stream_duplex: "readable-stream/duplex",
_stream_passthrough: "readable-stream/passthrough",
_stream_readable: "readable-stream/readable",
_stream_transform: "readable-stream/transform",
_stream_writable: "readable-stream/writable",
string_decoder: "string_decoder",
sys: "util",
timers: "timers-browserify",
tty: "tty-browserify",
url: "url",
util: "util",
vm: "vm-browserify",
zlib: "browserify-zlib"
},
}
core用モジュールの無効化
臭いものに蓋と巷では話題の方法です。
以下をwebpack.config.jsに追記してください。
resolve: {
alias: { ... },
fallback: {
child_process: false,
fs: false,
crypto: false,
net: false,
tls: false
}
}
上記の設定は 当該モジュールを要求するときは空のオブジェクトに変換する という方法です。
これで大体の人は動くようになるようです。
ただ、私の場合は uncaught ReferenceError: Buffer is not defined
と、また違うエラーが出て悩まされています。
ひとまず大抵の方はこれで動くようになるようなので、困っている方がいればぜひ試してみてください。
言葉足らずだったりわかりにくいところなどあればコメントで教えていただけると幸いです。
それじゃあまた。
uncaught ReferenceError: Buffer is not defined (2021/1/25 追記)
クライアントサイドで使用できない Buffer
が使われている? Webpackのせい?
わからなかったので調べてみたところこんなIssueが...
Buffer removed, it cause some trouble
ごめんなさい、ちゃんと内容を追っていないのですがクライアントサイドでBufferを使いたい(or使っているライブラリを使いたい)場合は、以下のようにwebpack.config.jsに追記をしてあげればいいようです。
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
})