Skip to content

fix: lazy-load cloudflare:workers to support non-Worker runtimes#193

Draft
LordCoughmann wants to merge 1 commit into
cloudflare:mainfrom
LordCoughmann:fix/lazy-cloudflare-workers-import
Draft

fix: lazy-load cloudflare:workers to support non-Worker runtimes#193
LordCoughmann wants to merge 1 commit into
cloudflare:mainfrom
LordCoughmann:fix/lazy-cloudflare-workers-import

Conversation

@LordCoughmann
Copy link
Copy Markdown

@LordCoughmann LordCoughmann commented May 28, 2026

Problem

The top-level import { env } from 'cloudflare:workers' causes the module to crash when loaded in non-Worker runtimes (Node.js, Deno, Bun, browsers). This prevents using connectOverCDP() with external CDP endpoints outside of Cloudflare Workers.

Reproduction: https://github.com/LordCoughmann/repo-cf-playwright-lazy-import

pnpm install
node index.mjs
# → Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported

Solution

Replace the static import with a lazy getter that resolves cloudflare:workers only when Browser Binding functions are actually called:

let _env: Record<string, any> | null = null;
function getEnv(): Record<string, any> {
  if (_env === null) {
    try {
      const { createRequire } = require('node:module');
      const cjsRequire = createRequire(import.meta.url);
      _env = cjsRequire('cloudflare:workers').env ?? {};
    } catch {
      _env = {};
    }
  }
  return _env;
}
  • In Workers: resolves normally, no behavior change
  • Outside Workers: falls back to {}, module loads successfully
  • env is only accessed by endpointURLString() and getBrowserBinding() — functions only called for Browser Binding workflows
  • Call-site errors unchanged: No binding found for ${binding} still fires if someone uses Browser Binding without a valid binding

We've been using @cloudflare/playwright@1.3.0 patched with this pattern in production with external CDP endpoints (Steel, Browserbase, local Chrome) and test environments (Node.js + Vitest).


I understand this is likely not a priority for the team. Happy to adjust the approach, or maintain this as a downstream patch if that's preferred. Any feedback welcome.

Refs: #88, #59

The top-level import of cloudflare:workers causes the module to crash
in non-Worker runtimes (Node.js, Deno, Bun, browsers). Replace with
a lazy getter using createRequire for ESM compliance. The module is
only resolved when Browser Binding functions are actually called.

Call-site errors (No binding found for X) remain unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants