できない.dev

webpack 5 で「process is not defined」やコアモジュールの解決に失敗する

webpack 5 の process is not defined は、resolve.fallback と ProvidePlugin で補えば直る。
webpack 5 が Node.js コアモジュールの自動 polyfill をやめたためだ。

公開: 更新:

症状できない · exit 1
npx webpack
…
ERROR in ./src/index.js 1:0-24
Module not found: Error: Can't resolve 'path' in '/tmp/tmp.FUSPmjBJVH/src'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
解決後できた · exit 0
npx webpack
…
  ./src/index.js 95 bytes [built] [code generated]
  ./node_modules/path-browserify/index.js 15.8 KiB [built] [code generated]
  ./node_modules/process/browser.js 5.29 KiB [built] [code generated]
webpack 5.110.3 compiled successfully in 73 ms

2026-09-10 に node:20(Node.js 20.20.2 / npm 10.8.2) で実際に打って取った出力。検証環境の詳細

要約

Uncaught ReferenceError: process is not defined や Module not found: Error: Can't resolve 'crypto' が webpack 5 へ上げた直後に出るのは、webpack 5 が Node.js コアモジュールの自動 polyfill を廃止したためだ。
webpack 4 は crypto や stream を自動で browserify 版に差し替えていたが、5 では何も入らない。

必要なものだけを自分で補うのが正しい対処になる。
まずバンドルサイズを増やさない選択肢から検討する。

// webpack.config.js
module.exports = {
  resolve: {
    fallback: { fs: false, path: require.resolve("path-browserify") },
  },
};

実行例

webpack 5.110.3 で path を import したまま束ねようとすると、Module not found が出た。
同じメッセージの中に、「webpack 5 は Node.js のコアモジュールを自動では補わない」という案内と、fallback を書くか false にするかの二択が示される。resolve.fallback に path-browserify と process/browser を割り当てた版と、fs: false で空モジュールに倒した版は、どちらも終了コード 0 でビルドが通った。

$ npx webpack
asset main.js 1.09 KiB [emitted] (name: main)
runtime modules 211 bytes 1 module
./src/index.js 95 bytes [built] [code generated]
 
ERROR in ./src/index.js 1:0-24
Module not found: Error: Can't resolve 'path' in '/tmp/tmp.FUSPmjBJVH/src'
 
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
 
If you want to include a polyfill, you need to:
	- add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
	- install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
	resolve.fallback: { "path": false }
resolve 'path' in '/tmp/tmp.FUSPmjBJVH/src'
  Parsed request is a module
  using description file: /tmp/tmp.FUSPmjBJVH/package.json (relative path: ./src)
    Field 'browser' doesn't contain a valid alias configuration
    resolve as module
      /tmp/tmp.FUSPmjBJVH/src/node_modules doesn't exist or is not a directory
      looking for modules in /tmp/tmp.FUSPmjBJVH/node_modules
        single file module
          using description file: /tmp/tmp.FUSPmjBJVH/package.json (relative path: ./node_modules/path)
            no extension
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path doesn't exist
            .js
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path.js doesn't exist
            .json
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path.json doesn't exist
            .wasm
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path.wasm doesn't exist
            .html
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path.html doesn't exist
            .css
              Field 'browser' doesn't contain a valid alias configuration
              /tmp/tmp.FUSPmjBJVH/node_modules/path.css doesn't exist
        /tmp/tmp.FUSPmjBJVH/node_modules/path doesn't exist
      /tmp/node_modules doesn't exist or is not a directory
      /node_modules doesn't exist or is not a directory
 
webpack 5.110.3 compiled with 1 error in 57 ms
$ echo $?
1
$ npx webpack
asset main.js 25.1 KiB [emitted] (name: main)
runtime modules 883 bytes 4 modules
cacheable modules 21.2 KiB
  ./src/index.js 95 bytes [built] [code generated]
  ./node_modules/path-browserify/index.js 15.8 KiB [built] [code generated]
  ./node_modules/process/browser.js 5.29 KiB [built] [code generated]
webpack 5.110.3 compiled successfully in 73 ms
$ echo $?
0
$ npx webpack
asset main.js 3.46 KiB [emitted] (name: main)
runtime modules 883 bytes 4 modules
cacheable modules 61 bytes
  ./src/index.js 46 bytes [built] [code generated]
  fs (ignored) 15 bytes [built] [code generated]
webpack 5.110.3 compiled successfully in 50 ms
$ echo $?
0

— 2026-09-10 時点の出力

検証環境Node.js 20.20.2 / npm 10.8.2 / Python 3.11.2 / 2026-09-10 検証(ほか 1 件)
検証日
実行環境
node:20 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

1. 必要なコアモジュールだけ fallback を指定する

polyfill パッケージを入れ、resolve.fallback で対応付ける。

npm install --save-dev path-browserify stream-browserify buffer
// webpack.config.js
module.exports = {
  resolve: {
    fallback: {
      path: require.resolve("path-browserify"),
      stream: require.resolve("stream-browserify"),
      buffer: require.resolve("buffer/"),
    },
  },
};

crypto-browserify のように数百 KB になる polyfill もある。
全部入れる前に、本当にブラウザで必要かを確認したほうがよい。

2. process / Buffer のグローバルを注入する

process と Buffer はモジュールではなくグローバル変数として参照されるため、resolve.fallback だけでは解決しない。ProvidePlugin で注入する。

// webpack.config.js
const webpack = require("webpack");
 
module.exports = {
  plugins: [
    new webpack.ProvidePlugin({
      process: "process/browser",
      Buffer: ["buffer", "Buffer"],
    }),
  ],
};

process/browser は process パッケージに含まれるブラウザ向け実装で、別途インストールが必要になる。

3. 使わないモジュールは空にする

到達しないコードパスで参照されているだけなら、polyfill を入れずに false を指定してバンドルから外す。

// webpack.config.js
module.exports = {
  resolve: {
    fallback: { fs: false, child_process: false, net: false },
  },
};

webpack 4 の node: { fs: 'empty' } はこの書き方に置き換わった。
設定の対応関係は公式の node オプション(新しいタブで開く)にまとまっている。

4. ブラウザに持ち込まない

一番確実なのは、そもそも巻き込まないことだ。
サーバー専用の処理を別モジュールへ切り出し、ブラウザ側のエントリから参照しないようにする。
環境変数を渡したいだけなら DefinePlugin で定数として埋め込めば process 自体が不要になる。

よくある原因

  1. 自動 polyfill が廃止された。
    webpack 5 はブラウザ向けビルドで Node.js コアモジュールを自動補完しない。移行ガイド(新しいタブで開く)にも、必要なら npm から互換モジュールを入れて自分で指定するよう書かれている。
  2. 依存パッケージが Node を前提にしている。
    自分のコードに process が無くても、依存の内部が process.env.NODE_ENV を読んでいれば同じエラーになる。
  3. webpack 4 の設定が残っている。node: { fs: 'empty' } は webpack 5 では機能しないので、resolve.fallback.fs: false に書き換える必要がある。
  4. サーバー専用のコードを巻き込んでいる。
    DB クライアントなどサーバー専用パッケージが、共通モジュール経由でブラウザ側の依存グラフに入っている。