Cloudflare · Deployment guide
Cloudflare Pages Node compatibility issues
Short answer
Cloudflare Workers isn't Node — it's a V8 isolate with selective Node compatibility. Most failures are either a missing nodejs_compat flag or a Node-only package that has no Worker build.
Symptoms
- Build succeeds but runtime throws “Cannot find module” for a Node built-in.
- Error: “[unenv] X is not implemented yet!” at request time.
- “__dirname is not defined” after the bundler emits ESM.
- Works in `wrangler dev` but crashes in production.
- Imports from sharp, canvas, puppeteer or any *.node binding fail.
Common causes
- nodejs_compat compatibility flag not enabled in wrangler.toml or Pages settings.
- Package depends on a native (.node) binding that doesn't ship in Worker bundles.
- Module uses child_process.spawn — stubbed on Workers, throws at call time.
- fs.watch / fs.watchFile used somewhere in the import graph.
- Build pulls in a CommonJS package that expects Node globals (__dirname, __filename).
How DeployDoc checks this
- Reads wrangler.toml and Pages compatibility flags; flags missing nodejs_compat.
- Scans dependencies for known Worker-incompatible packages (sharp, puppeteer, etc.).
- Catches direct imports of child_process / fs.watch / dgram in shipped code.
- Detects __dirname / __filename references that break under ESM bundling.
Fix it manually
- Add
compatibility_flags = ["nodejs_compat"]to wrangler.toml. - Set a compatibility_date from at least 2024-09-23 to enable the modern Node shims.
- Replace Node-only packages with Worker-compatible alternatives (e.g.
sharp→@cf-wasm/photon). - Remove imports of child_process, dgram, fs.watch.
- Test against a production bundle, not just
wrangler dev.
When to run a DeployDoc diagnosis
Whenever a Worker or Pages function works in dev but fails in production, or after adding a new npm dependency.