-
Notifications
You must be signed in to change notification settings - Fork 5k
Description
Summary
The current Teleport documentation shows to="body" as the primary example, which works in SPA but causes critical bugs (white screen, app crash) in SSR frameworks like Nuxt 3 and vike-vue during client-side navigation.
Problem
When using <Teleport to="body"> in SSR frameworks:
- Vue marks
document.bodyas a managed container - During CSR (client-side routing) navigation, when the component with Teleport unmounts
- Vue calls
unmountChildren(body)to clean up teleported content - This removes ALL body children, including the app root element (
#app,#__nuxt, etc.) - Result: white screen with no errors in console
Affected Frameworks
- Nuxt 3 - Has dedicated
#teleportscontainer - vike-vue - Has dedicated
#teleportedcontainer - Potentially any Vue 3 SSR framework with client-side navigation
Evidence
- Nuxt Issue #30639 - "App Routing breaks when navigating from a Page with Teleport"
- Nuxt Issue #24207 - "Teleport behaves differently for SSR and client-side"
- Test reproduction repo - Shows empty body after navigation
Proposed Documentation Change
Add a warning callout in the Teleport documentation after the basic example:
:::warning SSR Framework Consideration
When using Vue with SSR frameworks (Nuxt, vike-vue, etc.), avoid using `to="body"` as the teleport target. During client-side navigation, unmounting a component with `<Teleport to="body">` can remove the entire app root element, causing a white screen.
Instead, use the dedicated teleport container provided by your framework:
- **Nuxt 3**: `<Teleport to="#teleports">`
- **vike-vue**: `<Teleport to="#teleported">`
- **Other frameworks**: Check your framework's documentation for the recommended teleport target
This issue does not affect pure SPA applications.
:::Why This Matters
- Developers follow Vue documentation examples
- They use
to="body"as shown in the docs - App works initially but crashes on CSR navigation
- Debugging is extremely difficult (no console errors)
- Hours/days spent finding the root cause
Adding this warning would save countless developer hours and prevent frustration.
Additional Context
The technical reason: When Vue teleports content to body, it treats body as a managed container. On unmount, Vue's unmountChildren() function removes all children of the managed container, not just the teleported content. Since the app root (#app) is also a child of body, it gets removed.
SSR frameworks solve this by providing an isolated container (#teleports, #teleported) that Vue can safely manage without affecting the app root.