Skip to content

feat: Cloudflare Vite plugin integration - #15627

Closed
teemingc wants to merge 95 commits into
fetchable-dev-environmentfrom
cloudflare-vite-plugin
Closed

feat: Cloudflare Vite plugin integration#15627
teemingc wants to merge 95 commits into
fetchable-dev-environmentfrom
cloudflare-vite-plugin

Conversation

@teemingc

@teemingc teemingc commented Mar 31, 2026

Copy link
Copy Markdown
Member

closes #10496
closes #13692
closes #1712
closes #2963
closes #13300
closes #1519

This PR removes support for Cloudflare Pages and integrates with the Cloudflare Vite plugin. Users can now:

  • Use runtime APIs and bindings locally/remotely during build and preview.
  • Deploy apps unbundled by default (bundling is no longer required; saving a build artifact works again)
  • Write a custom worker entrypoint

TODOs

  • export a fetch handler for adapter-cloudflare
  • analysis in workerd
  • prerender in workerd
  • think about what tests are needed
  • split the PR up into removing Cloudflare Pages support and adding the Cloudflare Vite plugin

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@changeset-bot

changeset-bot Bot commented Mar 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8970286

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

This PR includes changesets to release 1 package
Name Type
@sveltejs/adapter-cloudflare Major

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

@svelte-docs-bot

Copy link
Copy Markdown

await expect(page.locator('#var')).toHaveText(`Var: ${prod_string}VAR`);
});

test('serves static assets with assets path prefix', async ({ page, request }) => {

@teemingc teemingc May 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not really sure how to get this test passing in the Cloudflare environment. Vite doesn't enforce consumers to allow us to run arbitrary code during preview so an alternative might be to have process.env.SVELTEKIT_ASSETS as an override which we set before anything else starts?

stolinski added a commit to syntaxfm/live-tools that referenced this pull request May 28, 2026
…1 (steps 1-3)

Steps 1-3 of docs/jazz-to-cloudflare-migration.md:
- Provision D1 + per-show ShowRoom and singleton ShowDirectory Durable Object
  bindings in wrangler.jsonc; generate binding types (pnpm cf:types).
- Switch SvelteKit to @sveltejs/adapter-cloudflare. Because the released adapter
  (pre sveltejs/kit#15627) writes its worker to wrangler's `main`, a second config
  (wrangler.adapter.jsonc) drives the adapter's output while the real wrangler.jsonc
  `main` is src/worker.ts — a custom entry that imports the built SvelteKit worker,
  re-exports the Durable Objects, and wraps fetch with @sentry/cloudflare.
- Port server Sentry to @sentry/cloudflare; delete instrumentation.server.ts and the
  adapter-node tracing/instrumentation settings.
- Move Better Auth off jazzAdapter to a per-request createAuth(env) factory using the
  Drizzle / drizzle-orm/d1 adapter. Hand-authored D1 schema (auth tables + registry:
  shows/showHosts/hostLinks) with a partial unique index enforcing one live show.
  drizzle-kit migrations applied to local D1.
- DEV_AUTH-gated dev-auth bypass (/dev-login) seeding an admin and a viewer, minting
  real JWKS-signed JWTs (verified: admin is_admin:true, viewer false).
- Repoint auth:schema/db:reset; drop auth:validate. Add cf:types/db:* scripts.

Deviations (documented): raw Durable Objects + WebSocket Hibernation API instead of
PartyServer; wrangler dev against the build is the DO-capable runtime loop instead of
@cloudflare/vite-plugin's vite dev, which cannot run a custom DO-exporting worker entry
with the current SvelteKit adapter. Jazz data path goes dark mid-migration (single
branch, no dual-path), restored on the new stack in steps 4-5.

check/lint/build all green; app + auth verified under wrangler dev via Chrome DevTools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aslakhellesoy added a commit to oselvar/sveltekit-add-worker-exports that referenced this pull request Jun 7, 2026
Links the two live upstream tracks: sveltejs/kit#15627 (adapter-cloudflare
adopting @cloudflare/vite-plugin) and the Durable Object / Workflow export
gap in cloudflare/workers-sdk#14013.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@badreddinesaadioui

badreddinesaadioui commented Jun 10, 2026

Copy link
Copy Markdown

tested this PR against a real production app: SvelteKit + a Durable Object (voice agent) exported from the same Worker, WebSockets, Workers AI with remote: true bindings, R2, and a handful of +server.ts endpoints. Today we use @oselvar/sveltekit-add-worker-exports to work around #1712, so this PR is exactly what we've been waiting for. Sharing results in case real-world feedback is useful at this stage.

Setup: installed via pkg.pr.new/@sveltejs/kit@15627 and pkg.pr.new/@sveltejs/adapter-cloudflare@15627, with vite@8.0.16, svelte@5.56.3, @sveltejs/vite-plugin-svelte@7, @cloudflare/vite-plugin@1.x, Node 22. Custom entrypoint per the new docs: main pointing at our own src/worker/index.ts that does import { fetch } from '@sveltejs/adapter-cloudflare/worker', re-exports the DO class, and export default { fetch }.

Findings, in the order we hit them:

  1. vite build fails during the analysis phase:

    Cannot find module 'SERVER' imported from node_modules/.vite-analyse/deps_ssr/@sveltejs_adapter-cloudflare_worker.js
    

    Same error reported above by another tester. Root cause appears to be that when the custom entrypoint imports @sveltejs/adapter-cloudflare/worker, Vite's dep optimizer pre-bundles that module, and the adapter's resolver for the virtual SERVER/MANIFEST ids never runs against the optimized copy. Adding optimizeDeps.exclude: ['@sveltejs/adapter-cloudflare/worker'] in user config (both top-level and ssr) did not help; the analysis server seems to spin up its own config. Maybe the adapter should exclude its own /worker subpath from dep optimization. This currently blocks the custom-entrypoint flow entirely, and since a DO class can only be exported from main, it blocks every Durable Object use case, which is the headline feature for us.

  2. vite dev fails before that with:

    The following environment options are incompatible with the Cloudflare Vite plugin:
    	- "ssr" environment: `resolve.external`: ["@floating-ui/dom","@iconify/types"]
    

    We never set resolve.external; vite-plugin-svelte auto-externalizes those (transitive deps of common Svelte UI libs, @iconify/svelte and svooltip in our case). So dev fails out of the box for apps using ordinary component libraries. Workaround: adding them to ssr.noExternal, after which we hit ReferenceError: exports is not defined from the runner, presumably a CJS dep now being executed raw in workerd. We stopped there.

  3. pkce-challenge (transitive dep of Cloudflare's own agents SDK via the MCP SDK) fails to resolve in the worker build: its exports map only has browser and node conditions, no default, so the workerd-conditions resolve finds nothing. Worked around with a resolve.alias to its browser build. Probably an ecosystem problem rather than this PR's, but anyone building a voice/agents app on Workers will hit it immediately.

  4. Minor setup friction worth documenting for testers: the preview kit imports rolldown at config-load time but doesn't ship it, so on a fresh install the build dies with ERR_MODULE_NOT_FOUND: rolldown until you install it manually. And with Vite 7 still installed (peer range is ^8.0.0, npm only warns with --legacy-peer-deps), the failure mode is a confusing Could not find file "src/routes/.../+server.ts" in Vite manifest for every endpoint rather than a version error.

Happy to re-test on this app as the PR evolves; it exercises pretty much everything at once (DO + WebSockets + remote AI bindings + custom entrypoint), so it's a decent canary.

@teemingc teemingc linked an issue Jun 15, 2026 that may be closed by this pull request
teemingc added a commit that referenced this pull request Jul 16, 2026
closes #16361

This PR adds the Cloudflare Workers-specific condition `workerd` to the
imports list in `package.json` so that Wrangler stops resolving to the
`browser` condition which exposes client-side code.

It's a quick fix that isn't needed if we land
#15627 which simply removes the
`browser` condition added by the Cloudflare Vite plugin for the build.
Once we use Cloudflare's Vite plugin, the builds get deployed unbundled
so we don't have to worry about Wrangler rebundling with the `browser`
condition like we do now.

---

### Please don't delete this checklist! Before submitting the PR, please
make sure you do the following:
- [x] It's really useful if your PR references an issue where it is
discussed ahead of time. In many cases, features are absent for a
reason. For large changes, please create an RFC:
https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it
solves.
- [ ] Ideally, include a test that fails without this PR but passes with
it.

### Tests
- [ ] Run the tests with `pnpm test` and lint the project with `pnpm
lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more
packages' changelogs, generate a changeset by running `pnpm changeset`
and following the prompts. Changesets that add features should be
`minor` and those that fix bugs should be `patch`. Please prefix
changeset messages with `feat:`, `fix:`, or `chore:`.

### Edits

- [x] Please ensure that 'Allow edits from maintainers' is checked. PRs
without this option may be closed.
@teemingc

Copy link
Copy Markdown
Member Author

Going to close this one until we can make better sense of the fetchable dev environment API in a way that doesn't make Kit worse for other platforms

@teemingc teemingc closed this Jul 30, 2026
@Giggiux

Giggiux commented Jul 31, 2026

Copy link
Copy Markdown

Going to close this one until we can make better sense of the fetchable dev environment API in a way that doesn't make Kit worse for other platforms

@teemingc I kinda don't understand this decision. What are the limits of the current Vite plugin/or the feature that would be worse for the other platforms supporting this?
Other major meta-frameworks support this (Tanstack/Astro for sure; not sure about Next, as I haven't used it in years, but vinext exists).

I personally tested SvelteKit 3 with this, and the only issue I had was the SERVER/MANIFEST error I linked (#15627 (comment)).

I also understand that I am missing some context on new features / architectural decisions, but for a Vite-based meta framework, it seems odd that it cannot support a Vite Plugin.

I am sorry for the next phrase. I really hope this is not a decision stemming from the ongoing Vercel/Cloudflare feud.

@teemingc

teemingc commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

I also understand that I am missing some context on new features / architectural decisions, but for a Vite-based meta framework, it seems odd that it cannot support a Vite Plugin.

The main issue is that supporting Vite's FetchableDevEnvironment interface requires a major rework to the Kit codebase that unnecessarily complicates it and in some cases downgrades it for a use case that only supports Cloudflare. This negatively impacts every other platform (Node, Vercel, Netlify, Bun, etc.). It's also blocking a lot of other useful PRs because of the constant merge conflicts (we're trying to ship SvelteKit 3)

I am sorry for the next phrase. I really hope this is not a decision stemming from the ongoing Vercel/Cloudflare feud.

Not to worry, I'm not even paid by Vercel 😆; I'm supported by the Svelte open collective (in fact, I'm a happy Cloudflare user and have been using it to host church sites for a few years now). Also, we haven't given up yet. We're still thinking about the best way to do this that doesn't require such a massive change. Will report back soon if my findings are successful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment