Skip to content

Do not deprecate wrangler's proxy feature, e.g. wrangler pages dev -- vite or keep at least the injection part with a new api such as wrangler inject -- vite #5315

Closed

Description

@newsve

Edit: I edited the issue title since this thread has been evolved about how to inject CF env vars into a hot reloading dev server, the actual issue is further down: #5315 (comment)

Which Cloudflare product(s) does this pertain to?

Pages

What version(s) of the tool(s) are you using?

3.35.0

What version of Node are you using?

v20.11.1

What operating system and version are you using?

Ubuntu 22.04.2 LTS

Describe the Bug

Observed behavior

When the app redirects wrangler pages dev does the redirect but the URL in the browser's URL bar doesn't change (or redirect's header lacks the redirect status and new URL and the response header lacks a location header.

This is a big problem because it breaks relative links on redirected pages and doesn't reflect production.

Expected behavior

A proper redirect with URL change and proper headers

Steps to reproduce

git clone https://github.com/newsve/wrangler-no-redirect.git
npm i
npm run dev

In your browser go first to localhost:5713 which is the og SvelteKit/Vite server without wrangler, you see a redirect happng to localhost:5713/some-random-page. Now try the same with localhost:8788 which is via wrangler, still redirects but the URL in the URL bar does not change.

Also check and compare the headers (left: 5713, right 8788), note that the 8788 one lacks a response location header:

image

Please provide a link to a minimal reproduction

git clone https://github.com/newsve/wrangler-no-redirect.git

Please provide any relevant error logs

No response

Activity

  1. GregBrimble commented on Mar 20, 2024

    @GregBrimble
    Contributor

    Thanks for the report. This can be fixed by building assets to a directory and pointing Wrangler at that (wrangler pages dev <directory>), rather than using the proxy feature (wrangler pages dev -- <command>). This proxy feature will be deprecated shortly because of incompatibilities like you flag in this issue: #5317.

  2. newsve commented on Mar 20, 2024

    @newsve
    Author

    Thanks for your prompt answer.

    When I develop I usually don't have a build yet which wrangler pages dev could consume. And, I assumed wrangler pages dev is for developing, so running dev envs with HMR and live reload, etc., it is not meant for testing static production builds without hot realod/HMR. Please correct me if I am wrong.

    Most modern web frameworks are based on Vite and when I look into, e.g. SvelteKit's output folder .svelte-kit I don't see any cloudflare/ folder when in developing mode (vite dev or just vite). Only when I do a build with vite build, then I see that folder. But actually I never do latter because CF does this automatically when pushing to GH. So, not sure how the dev workflow would be then.

    So, maybe I do miss something and you can hint me with an example wrangler command targeting a Vite framework such as SvelteKit how this should work when developing with hot reload. Thanks!

  3. GregBrimble commented on Mar 20, 2024

    @GregBrimble
    Contributor

    Yes, unfortunately the best we can suggest right now is running vite build --watch (https://vitejs.dev/guide/build#rebuild-on-files-changes) and simultaneously, wrangler pages dev <directory>. We're actively considering how to improve this experience, so please bear with us. cc @dario-piotrowicz

  4. newsve commented on Mar 20, 2024

    @newsve
    Author

    But will wrangler pages dev still inject Cloudflare binds, e.g. to services like KV, or the props on request.cf, so the framework can consume those? This is somewhat the key USP of wrangler.

  5. GregBrimble commented on Mar 20, 2024

    @GregBrimble
    Contributor

    Yes, it will.

  6. newsve commented on Mar 20, 2024

    @newsve
    Author

    Just an idea:

    Right now, I use only the output of vite's dev server on 5173 despite wrangler started and proxied latter. And it is great because it has already all injected binds without the need to use wrangler's proxied version on 8788.

    A dev doesn't need more. So if there is way to get just the binds injected into vite dev without actually wrangler proxying vite would be already a huge step (because something like vite build --watch isn't as nice as vite dev for development).

  7. IgorMinar commented on Mar 20, 2024

    @IgorMinar
    Contributor

    hi @newsve, if you use the latest cloudflare adapter for sveltekit it will allow you to access all the bindings from within sveltekit's dev server. you can scaffold a new project using create-cloudflare to test it out and check out https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-site/#sveltekit-cloudflare-configuration - the docs don't mention it yet (WIP) but you can configure the bindings via wrangler.toml. Again, check out a clean create-cloudflare project where all of this is preconfigured already.

  8. newsve commented on Mar 20, 2024

    @newsve
    Author

    Thanks, I just skimmed through a create-cloudflare installation, and wow, super impressive! All the supported frameworks and in one place, amazing!

    One question though: I can't use the locally emulated Cloudflare services anymore like with wrangler in dev mode (wrangler doesn't run with npm run dev, just with build and preview), so I would need to bind my local dev server with an actual Cloudflare service in the cloud and have there always min. two of each kind (one for dev and one for production).

    Did I get it right?

  9. IgorMinar commented on Mar 20, 2024

    @IgorMinar
    Contributor

    Did I get it right?

    not quite, with the create-cloudflare integration we start a wrangler/miniflare process behind the scenes and integrate it into vite. So you can access a local D1 database, or KV store from your app while it's running via vite dev

  10. newsve commented on Mar 20, 2024

    @newsve
    Author

    Incredible! Is vite then somehow patched? Because in package.json, I only find "dev": "vite dev", (or do you mean the preview and build scripts?) and in vite.config.js I find no invocation of wrangler/miniflare either:

    import { sveltekit } from '@sveltejs/kit/vite';
    import { defineConfig } from 'vitest/config';
    
    export default defineConfig({
            plugins: [sveltekit()],
            test: {
                    include: ['src/**/*.{test,spec}.{js,ts}']
            }
    });
  11. newsve commented on Mar 21, 2024

    @newsve
    Author

    tl;dr:

    • Deprecating Wrangler's proxy functionality also with the new create-cloudflare CLI risks degrading developer experience by losing key development features like live reload and HMR, repro steps for Svelte below but this issue is with every framework, Svelte acts as an example here
    • This change may push developers towards other platforms due to reduced testing convenience; this is critical because the workers-sdk acts as the gateway and catalyst for utilizing all other Cloudflare services
    • Suggestion: Allow Cloudflare feature injection in npm run dev without full proxy use, to retain essential development tools

    Hey Cloudflare Team,

    Wanted to flag again a potential issue with deprecating Wrangler's Pages Dev Proxy functionality. Please follow these steps setting up a Svelte project with your new create-cloudflare CLI (which is again highly impressive!):

    npm create cloudflare@latest // Chose Create app/Website o. app/Svelte/Typescript

    Now, add src/routes/+page.server.ts:

    import type { PageServerLoad } from './$types'
    
    export const load: PageServerLoad = async ({ request }) => {
      console.log(request.cf)
      return
    }

    Try npm run dev and check the server logs, access the new app in your browser, console.log prints nothing.

    Try npm run preview and check the server logs, and yes, request.cf is set! but you don't get:

    1. Must-have: Rebuild on file changed (somehow doesn't work)
    2. Must-have: Live-reload in the browser (this wouldn't work if even 1 did work)
    3. Nice-to-have: HMR in the browser (this wouldn't work if even 1 did work)

    2 and 3 rely on Vite's unmatched dev server which is key to Vite's success and which you can't use with npm run preview.

    The current developer experience with Cloudflare services takes a hit due to the necessity of restarting the server or refreshing the browser on every file change. This becomes especially problematic for those relying on Cloudflare-specific features, such as request.cf, to dynamically adjust behavior based on the node's location. The cumbersome workaround of using npm run preview isn't a viable solution for a smooth and efficient development workflow.

    I'm concerned this move might push developers towards alternative solutions or other providers, particularly when the ease of integration and testing of CF services is compromised. The deprecation of wrangler pages dev -- could lead to missed opportunities in leveraging Cloudflare to its full potential.

    Would it be possible to explore a solution that allows injecting Cloudflare's features into the development environment, specifically through npm run dev, e.g. with something like wrangler inject -- vite, without fully acting as a proxy? Currently, I bypass the proxy's verbosity on 8788 and limitations by directly using Vite's output on 5173. So, we would need just the injecting part of wrangler pages dev -- vite.

  12. aroman commented on Mar 22, 2024

    @aroman

    Strongly agree with @newsve's points above... I was shocked to learn that wrangler is deprecating the proxy feature without a viable replacement (vite build --watch will not meet our needs).

    To be clear: hot-reload support is not a "nice-to-have" for us, it is essential to our workflow: we literally cannot develop without it. Our application has a lot of intricate client state (we're building games) and forcing hard-reloads fundamentally breaks our team's workflow. cc: @admah

  13. 32 remaining items

  14. ilyakam commented on Jan 28, 2025

    @ilyakam

    @vmuthal solution also works with Astro! Here's how:

    1. Set up a new Cloudflare Pages + Astro project
    2. pnpm add -D concurrently
    3. Update the "scripts" in package.json:
    {
      "scripts": {
        "dev": "concurrently --kill-others-on-fail \"pnpm run dev:astro\" \"pnpm run dev:wrangler\"",
        "dev:astro": "astro dev",
        "dev:wrangler": "wrangler pages dev --proxy 4321 --port 8788"
      }
    }

    To verify the KV bindings:

    1. Add your kv_namespaces to wrangler.json per these docs

    2. Update Welcome.astro to:

    ---
    const { env } = Astro.locals.runtime;
    
    const foo = await env.FOO.list(); // or `.get()` etc.
    ---
  15. madsem commented on Jan 28, 2025

    @madsem

    Not a solution @vmuthal as they are removing the --proxy flag...
    That will make it impossible to work in monorepos / multi site repos btw @GregBrimble

    Would require largescale changes, building / copying builds into directories to serve from, not to mention CI pipelines.
    I'm sure there are good reasons to want to remove this, but personally I'm pretty frustrated by this and the lack of alternatives.

    "Build into a directory and start wrangler from there" is not a real alternative...

    How would you now for example run the global _middleware.js on all requests like in production? For AB testing. This is going to make local dev extremely uncomfortable imo

  16. ricky11 commented on Mar 17, 2025

    @ricky11

    Cant work with pages functions without HMR in dev mode, is their a solution?

  17. braden-w commented on Apr 4, 2025

    @braden-w

    As a temporary fix, I ended up with this hybrid approach.

    import type { D1Database } from "@cloudflare/workers-types";
    import * as schema from "@repo/db";
    import { getEvent } from "@tanstack/react-start/server";
    import { drizzle } from "drizzle-orm/d1";
    
    type Env = { DB: D1Database };
    
    async function getEnv(): Promise<Env> {
    	// In development, we can use getPlatformProxy (https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy)
    	// We cannot use it in production because `import { getPlatformProxy } from "wrangler"` causes an error in build
    	if (process.env.NODE_ENV === "development") {
    		const { getPlatformProxy } = await import("wrangler");
    		const { env } = await getPlatformProxy<Env>();
    		return env;
    	}
    	// In production, the bindings are attached to the event in event.context.cloudflare.env https://nitro.build/deploy/providers/cloudflare#direct-access-to-cloudflare-bindings
    	const env = getEvent().context?.cloudflare?.env as Env | undefined;
    	if (!env) {
    		throw new Error("Cloudflare environment is not attached to the event.");
    	}
    	return env;
    }
    
    // Example creating a context for a TRPC router
    export async function createContext() {
    	const env = await getEnv();
    	const db = drizzle(env.DB, { schema, logger: true });
    
    	return { db };
    }
    1. In Dev Mode: Use const { env } = await getPlatformProxy<Env>(). getPlatformProxy creates an object that emulates the Cloudflare bindings in Node.js, as explained here.

      • Dynamically imported with const { getPlatformProxy } = await import("wrangler") to prevent wrangler from being included in production build. This is because although it works in dev, it doesn't work with vinxi build in TanStack Start because the import { getPlatformProxy } from "wrangler" gives the following error:

        ... ERROR Unexpected token production. Expected identifier in /Users/.../.../.../node_modules/.pnpm/wrangler@4.7.0_@cloudflare+workers-types@4.20250404.0/node_modules/wrangler/wrangler-dist/cli.js

        Image

    2. In Production: Use const event = await getEvent() (or your framework's equivalent) to access the event in Nitro.

      • In Cloudflare, Nitro attaches the Cloudflare bindings to event's context.cloudflare.env, as described here.

    Now, I can access Bindings in vinxi dev with HMR rather than having to use wrangler pages dev. This is still a hackery fix, hopefully not necessary as bundling in dev and production gets more unified. Hope this helps!

  18. braden-w commented on Apr 13, 2025

    @braden-w

    Update, Cloudflare has recently released announced their official Vite plugin (@cloudflare/vite-plugin) that can integrate with any Vite-based application and emulate the worker runtime in development.

    You can now simply:

    pnpm add -D @cloudflare/vite-plugin
    // vite.config.ts
    import { defineConfig } from "vite";
    import { cloudflare } from "@cloudflare/vite-plugin";
    
    export default defineConfig({
      plugins: [cloudflare()]
    });

    in any Vite app.

    Now, our Worker code can run inside the native Cloudflare Workers runtime (workerd) during development, and the dev server matches the production behavior as closely as possible (compared to the getPlatformProxy approach from before).

  19. KyGuy2002 commented on Apr 24, 2025

    @KyGuy2002

    Has anyone been able to get the new vite plugin to work with cloudflare pages?

    For me it only serves the static assets, I think its just treating it as a worker and not a pages project so its ignoring the /functions directory.

  20. anhtuank7c commented on Jun 24, 2025

    @anhtuank7c

    Has anyone successfully run a SvelteKit application with @cloudflare/vite-plugin?
    I tried to edit vite.config.ts as @braden-w mention from above but doesn't seem to work.
    I use workers to run SvelteKit application, NOT pages.

    https://developers.cloudflare.com/workers/static-assets/migration-guides/migrate-from-pages/

  21. added theissue type on Oct 30, 2025
  22. penalosa commented on Mar 19, 2026

    @penalosa
    Contributor

    As mentioned earlier in this thread, @cloudflare/vite-plugin is the recommended approach for local dev with Vite and Cloudflare bindings. It runs your Worker in the native workerd runtime with full HMR support, and so no proxy layer is needed.

    We're gradually expanding framework support. Today, React Router, TanStack Start, and Astro integrate with the Vite plugin directly, and more frameworks are being added over time.

    For frameworks not yet supported, getPlatformProxy() remains available.

  23. moved this from Backlog to Done in workers-sdkon Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

product:pagesRelating to Cloudflare Pages: https://pages.cloudflare.com/

Type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions