Skip to content

[vite-plugin] fix: allow Node.js built-ins in resolve.external for Worker environments#14218

Merged
jamesopstad merged 6 commits into
cloudflare:mainfrom
matingathani:fix/vite-plugin-vitest4-resolve-external
Jun 17, 2026
Merged

[vite-plugin] fix: allow Node.js built-ins in resolve.external for Worker environments#14218
jamesopstad merged 6 commits into
cloudflare:mainfrom
matingathani:fix/vite-plugin-vitest4-resolve-external

Conversation

@matingathani

@matingathani matingathani commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #14215.

Root cause

Vitest 4 added an internal runnerTransform plugin that automatically sets resolve.external to the full list of Node.js built-in module specifiers for any Vite environment not named __vitest_vm__ or __vitest__. Since Cloudflare Worker environments have custom names, they receive this automatic resolve.external injection.

The Cloudflare Vite plugin's validateWorkerEnvironmentOptions previously threw on any non-empty resolve.external array, causing a startup error:

Error: The following environment options are incompatible with the Cloudflare Vite plugin:
    - "cloudflare_vite_vitest" environment: `resolve.external`: ["_http_agent", "assert", ...]
To resolve this issue, avoid setting `resolve.external` in your Cloudflare Worker environments.

Fix

Node.js built-in module entries (both bare fs and node:fs prefixed forms) are now filtered out before validation using node:module's builtinModules list. The error is only thrown when resolve.external is true (externalize everything unconditionally) or contains non-built-in package names that would prevent user code from being bundled.


  • Tests
    • Tests included/updated
  • Public documentation
    • Documentation not necessary because: internal validation behaviour fix for Vitest 4 compatibility, no new user-facing API

Open in Devin Review

…rker environments

Fixes cloudflare#14215.

Vitest 4 automatically adds all Node.js built-in module specifiers to
`resolve.external` for non-standard Vite environments via its internal
`runnerTransform` plugin. The Cloudflare Vite plugin previously threw on
any non-empty `resolve.external` array, causing a startup error when
Vitest 4 is used alongside the plugin.

Filter out Node.js built-in entries (bare and node:-prefixed forms) before
validation. Only throw when resolve.external is `true` (externalize
everything) or contains non-built-in package names.
Copilot AI review requested due to automatic review settings June 8, 2026 08:04
@changeset-bot

changeset-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: acde302

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk Jun 8, 2026
@workers-devprod workers-devprod requested review from a team and ascorbic and removed request for a team June 8, 2026 08:05
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/vite-plugin-vitest4-resolve-external.md: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/tests/validate-worker-environment-options.spec.ts: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/vite-config.ts: [@cloudflare/wrangler]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@pkg-pr-new

pkg-pr-new Bot commented Jun 8, 2026

Copy link
Copy Markdown
create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@14218

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@14218

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@14218

miniflare

npm i https://pkg.pr.new/miniflare@14218

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@14218

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@14218

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@14218

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@14218

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@14218

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@14218

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@14218

wrangler

npm i https://pkg.pr.new/wrangler@14218

commit: acde302

@petebacondarwin petebacondarwin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a way for Vitest to signal to our vite-plugin that it is adding node builtins as external so that we can skip only in this case?

Comment thread packages/vite-plugin-cloudflare/src/vite-config.ts
@workers-devprod

workers-devprod commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • ✅ @cloudflare/wrangler
Show detailed file reviewers

@matingathani

Copy link
Copy Markdown
Contributor Author

I wonder if there is a way for Vitest to signal to our vite-plugin that it is adding node builtins as external so that we can skip only in this case?

I looked into this. Vitest 4's runnerTransform plugin doesn't expose a dedicated signal — it silently injects node builtins into resolve.external for every non-vitest-internal environment. We could detect Vitest by inspecting resolvedViteConfig.plugins for a name starting with 'vitest:', but that couples us to Vitest's internal plugin naming (unstable across versions).

The current check is more principled: rather than "skip if Vitest is present," it's "allow resolve.external that contains only Node.js built-in specifiers." This is semantically correct — the Worker runtime handles node built-in imports regardless, so externalizing them is always safe. It also handles any other tool that might inject builtins into resolve.external in the future.

Happy to explore the Vitest-specific detection route if you'd prefer it — just let me know.

@petebacondarwin petebacondarwin requested review from jamesopstad and removed request for ascorbic June 16, 2026 08:37

@jamesopstad jamesopstad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

@workers-devprod workers-devprod left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codeowners reviews satisfied

@github-project-automation github-project-automation Bot moved this from Untriaged to Approved in workers-sdk Jun 17, 2026
@jamesopstad jamesopstad merged commit 4eed569 into cloudflare:main Jun 17, 2026
59 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in workers-sdk Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[vite-plugin] Vitest errors on startup with Cloudflare Vite plugin

5 participants