Skip to content

Routing Conflict with @cloudflare/vite-plugin in React SPA #8879

Description

@werkamsus

Which Cloudflare product(s) does this pertain to?

Vite Plugin

What versions & operating system are you using?

wrangler: ^4.7.0, vite: ^6.1.0, @cloudflare/vite-plugin: ^1.0.2, hono: ^4.7.5, react: ^19.0.0 (Node.js: unknown, C3: unknown)

Please provide a link to a minimal reproduction

No response

Describe the Bug

Routing Conflict with @cloudflare/vite-plugin in React SPA

When using the @cloudflare/vite-plugin in a React SPA setup—such as the vite-react-template or any custom project following a similar structure—a routing conflict occurs when attempting to directly navigate to server-side API routes via the browser.

Problem Description

This happens because the SPA fallback behavior (enabled by setting "not_found_handling": "single-page-application" in wrangler.json) intercepts requests with Sec-Fetch-Mode: navigate before the Worker script executes. As a result, the SPA’s index.html is served even for intended API routes.

This breaks scenarios where API routes need to be reachable directly from the browser, such as:

  • OAuth callbacks (e.g., /api/auth/callback/...)
  • Server-initiated redirects to API endpoints

Note: Programmatic fetch calls from the SPA to /api/* routes still work as expected, since they use cors mode and do reach the Worker.


Use Case / Impact

This breaks critical server-side functionality that relies on direct browser interaction with API routes, including:

  • OAuth callback handling from providers like Google or GitHub
  • Redirect-based flows where the browser is expected to land on a server-side route

Steps to Reproduce (Conceptual)

  1. Set up a project using either the vite-react-template or a custom project using @cloudflare/vite-plugin with Hono.
  2. Define a simple API route in Hono:
    app.get('/api/test', (c) => c.text('API OK'))
  3. Deploy using default or SPA-configured wrangler.json.
  4. Attempt to visit https://<your-worker-url>/api/test directly in the browser.

Expected Behavior

The API handler should respond with API OK.

Actual Behavior

The SPA’s index.html is served instead, and the Hono route is bypassed.


Troubleshooting / Workarounds Attempted

  1. Changing not_found_handling

    • Switching to "404" allows API routes to work
    • But breaks SPA routing
    • Requires manually serving index.html from Hono, which adds complexity
  2. Using run_worker_first

    • Setting run_worker_first: true along with SPA fallback and a valid assets config does allow the Worker to run first
    • But for the SPA to still work, a catch-all fallback route is needed in Hono like:
      app.get('*', (c) => c.env.ASSETS.fetch(c.req.raw))
    • This pattern is not included in the default template and isn’t obvious unless you read deeper into the docs
  3. Header Workarounds

    • Attempted to handle requests based on Sec-Fetch-Mode
    • But routing decisions are made before reaching the Worker

Question / Suggestion

What’s the recommended approach for using @cloudflare/vite-plugin with React (whether using the vite-react-template or a custom setup) to support both SPA behavior and direct browser access to API routes?

If the correct pattern is:

  • run_worker_first: true
  • not_found_handling: "single-page-application"
  • A proper assets config
  • A final catch-all Hono route to serve assets

...could this be documented more clearly or baked into the template directly?

Many full-stack use cases will hit this routing issue, and the workaround isn’t obvious without digging.


Environment

  • wrangler: ^4.7.0
  • @cloudflare/vite-plugin: ^1.0.2
  • vite: ^6.1.0
  • hono: ^4.7.5
  • react: ^19.0.0
  • node: [e.g., 20.x.x]

Thanks for maintaining these tools and templates!

Please provide any relevant error logs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature:workers-assetsRelating to Cloudflare Workers Assets: https://developers.cloudflare.com/workers/static-assets/package:vite-pluginRelating to the `@cloudflare/vite-plugin` package

    Type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions