Posted at

webpack 実行で Module not found: Error: Can't resolve 'fs' というエラー


概要

まずはこのエラーを見て欲しい

Module not found: Error: Can't resolve 'fs'

'fs' の部分は実に様々な内容に変わる

今日はこのエラーと向き合う


前提

node.js とかでフロントエンドとかバックエンドとか書いてて

トランスパイラ(babelとか)とモジュールバンドラ(webpackとか)の組み合わせで

開発する機会ってあると思うんだけど、

こいつらが何をしてるか?何が目的か?メリットは?デメリットは?って理解してないと

エラーが出た時焦るよな

ほんで今回はこのエラー、ぱっと見はすごく厄介そう

エラーを理解してないと間違った対処して、

babelやwebpackの恩恵を受けられていないことに気付けなくなる


この対処法は違う(と思うんだ)


fs: "empty" は間違い

この対応は臭いものに蓋をしているだけ

目を瞑ってる

根本的に何も解決できていないと思うんだ

もうちょっというと、自分で不具合の種を仕込んでる

私はこのコードがどう動いているかは理解できない


webpack.config.js

node: {

fs: "empty"
}

さらに、Angularとかだとwebpackとか意識せずに勝手にやってくれてる!みたいなイメージの人も多いと思う

webpack.config.js がないケースとかね

だからといって、

力技でpackage.json とかに書いちゃうのも違う気がする

だって、このコード違和感ない?


package.json

"browser": {

"fs": false
}


target: 'node' は理解していないと危ない

ちゃんとしたドキュメントに書いてある対処法

https://jlongster.com/Backend-Apps-with-Webpack--Part-I


webpack.config.js

var path = require('path');

module.exports = {
entry: './src/main.js',
target: 'node',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
}
}


でも、target: 'node'って書くからにはなぜ、target: 'node'と書くと動くのか?を理解しておいてもらいたい

バックエンドならいいと思う

だって、node.jsで書いてるんだよな?

だから、target: 'node' は正しい

なぜこう書くか?を理解できているならこれでいいと思う


こうじゃないか?

ここが重要

externals: nodeModules

これなら、fs: "empty" なんていう危険なコード仕込まなくたっていい

target: 'node' なんて決めつけなくていい


webpack.config.js

var webpack = require('webpack');

var path = require('path');
var fs = require('fs');

var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});

module.exports = {
entry: './src/main.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'backend.js'
},
externals: nodeModules
}