The error, verbatim
Jump to the fix ↓ throw Error('Dynamic require of "' + x + '" is not supported');
^
Error: Dynamic require of "fs" is not supported
# with react marked external:
Error: Dynamic require of "react" is not supported
# on Cloudflare Workers (wrangler dev):
[wrangler:error] Error: Dynamic require of "path" is not supported
Tested on
- esbuild
- 0.28.2
- Node
- 24.14.0
- wrangler
- 4.139.0
- Packages
- fs-extra 11.4.1, react 19.3.0
- OS
- Windows 11 Pro
The build works, and then the bundle crashes the moment it runs. The name in quotes is the package some CommonJS code tried to require(). It’s usually not your code: a dependency did it.
The fix
Your bundle is an ES module, and ES modules have no require. Pick the fix that fits how the bundle runs:
1. Output CommonJS instead. If the bundle runs in Node and nothing needs it to be ESM, this is the simplest:
npx esbuild src/index.mjs --bundle --platform=node --format=cjs --outfile=dist/out.cjs2. Keep ESM, and give the bundle a real require (Node only):
npx esbuild src/index.mjs --bundle --platform=node --format=esm --outfile=dist/out.mjs --banner:js="import { createRequire } from 'module'; const require = createRequire(import.meta.url);"In a build script, the same banner goes in banner: { js: "..." }.
3. If the require is inside a package, don’t bundle node_modules. Node then loads each package itself, CommonJS included:
npx esbuild src/index.mjs --bundle --platform=node --format=esm --packages=external --outfile=dist/out.mjs4. If the name is a package you marked external (like --external:react), either stop marking it external so esbuild bundles it, or use fix 2.
Why it happens
When esbuild bundles a CommonJS file into ES module output, it can’t turn every require() into an import. For the ones it leaves, it writes this stub at the top of your bundle:
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
It calls the real require if one exists, and throws if not. In an ES module there isn’t one. That’s why fix 2 works: the banner defines require before the stub runs.
On Cloudflare Workers
Workers behave differently, and it changes the fix. Through wrangler’s own bundler, plain require() calls worked in a CommonJS file, with or without nodejs_compat:
require() in a CommonJS dependency |
Result on Workers |
|---|---|
require('fs') |
worked |
require('node:crypto') |
worked |
require('buffer') |
worked |
require(name), with the name built at runtime |
Dynamic require of "path" is not supported |
The last one failed with nodejs_compat on as well. The bundler can only handle a require whose name it can read at build time. Change require(name) to the literal require('path'), and the same Worker returned 200.
What didn’t work
How this was tested
A small project with an ES module entry importing a local CommonJS file that calls require('fs'), a second entry using fs-extra 11.4.1 from npm, and a CommonJS file requiring react 19.3.0 with react marked external. Each was bundled with esbuild 0.28.2 in every variant above and run with Node 24.14.0. The Workers table comes from wrangler dev 4.139.0 with compatibility_date 2026-09-01, run once without and once with nodejs_compat.
— N.K., end of entry No.028