Skip to content

fix(fullstack): use target_arch instead of feature flags for server/web platform detection#5302

Closed
raxosiris wants to merge 1 commit intoDioxusLabs:mainfrom
gamescriptai:hydration-fix
Closed

fix(fullstack): use target_arch instead of feature flags for server/web platform detection#5302
raxosiris wants to merge 1 commit intoDioxusLabs:mainfrom
gamescriptai:hydration-fix

Conversation

@raxosiris
Copy link
Copy Markdown

Problem

In fullstack workspaces with multiple crates, Cargo's feature unification enables both web and server features simultaneously on dioxus-fullstack-core. This causes SSR hydration to break because code guarded by #[cfg(feature = "server")] and #[cfg(feature = "web")] both compiles and executes.

For example, in history.rs, the server branch (entry.insert()) runs in WASM instead of the client branch (entry.get()), causing hydration data to be overwritten instead of read.

Reproduction

  1. Create a fullstack workspace with a shared UI crate:
workspace/
  packages/app/     # depends on dioxus with features ["server"] or ["web"]
  packages/ui/      # depends on dioxus with features ["router", "fullstack"]
  1. The ui crate unconditionally enables fullstack, which pulls in both dioxus-fullstack-core/web and dioxus-fullstack-core/server through transitive feature resolution.

  2. Run dx serve — SSR renders correctly on the server, but WASM hydration fails because server-side code paths execute in the browser (e.g., entry.insert() instead of entry.get() in history.rs).

Fix

Replace cfg(feature = "server") / cfg(feature = "web") with cfg(not(target_arch = "wasm32")) / cfg(target_arch = "wasm32") in platform-specific code paths.

Why this works: target_arch is determined by the compilation target, not Cargo features, so it can never be both values simultaneously. dx serve compiles the server for native (x86_64/aarch64) and the client for wasm32 — these are separate compilation units immune to feature unification.

Why this is safe for other platforms:

  • Desktop, mobile, native, and liveview have no dependency on fullstack-core
  • fullstack-core is only compiled for server (via dioxus-server) and web client (via dioxus-web with hydrate)
  • The fullstack crate itself already uses target_arch = "wasm32" for websocket transport in client.rs, establishing this as the correct pattern

Changes

  • fullstack-core/src/history.rs — Route finalization: server inserts route, client reads it
  • fullstack-core/src/loader.rs — Data loader serialization direction
  • fullstack-core/src/server_cached.rs — Cache write (server) vs read (client)
  • fullstack-core/src/server_future.rs — Server future serialization direction
  • fullstack-core/src/transport.rsis_hydrating() and serialize_context() platform detection
  • fullstack-server/src/ssr.rs — Added explicit type annotation to has_context::<HydrationContext>()
  • web/src/lib.rsshould_hydrate now respects runtime config only, removing cfg!(feature = "hydrate") override that could be incorrectly triggered by feature unification

Cargo feature unification enables both `web` and `server` features
simultaneously in fullstack workspaces, breaking SSR hydration.
@raxosiris raxosiris requested a review from a team as a code owner February 9, 2026 12:37
@ealmloff
Copy link
Copy Markdown
Member

ealmloff commented Feb 9, 2026

We don't rely on the target to determine web vs server builds because the server can also be compiled to wasm on serverless targets like spin/fly.io. Your setup instructions sound very similar to the dioxus template workspace fullstack + router setup which does work correctly with hydration. Can you compare your feature setup to the template to narrow down the issue?

@ealmloff ealmloff added the fullstack related to the fullstack crate label Feb 9, 2026
@ealmloff ealmloff closed this Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fullstack related to the fullstack crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants