Skip to content

Add SSR Framework Warning to Teleport Documentation #3333

@Perlover

Description

@Perlover

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:

  1. Vue marks document.body as a managed container
  2. During CSR (client-side routing) navigation, when the component with Teleport unmounts
  3. Vue calls unmountChildren(body) to clean up teleported content
  4. This removes ALL body children, including the app root element (#app, #__nuxt, etc.)
  5. Result: white screen with no errors in console

Affected Frameworks

  • Nuxt 3 - Has dedicated #teleports container
  • vike-vue - Has dedicated #teleported container
  • Potentially any Vue 3 SSR framework with client-side navigation

Evidence

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

  1. Developers follow Vue documentation examples
  2. They use to="body" as shown in the docs
  3. App works initially but crashes on CSR navigation
  4. Debugging is extremely difficult (no console errors)
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions