nuxt / nuxt

The Intuitive Vue Framework.
https://nuxt.com
MIT License
55.05k stars 5.04k forks source link

<NuxtLayout> within <Teleport defer> throws warning: "Your project has pages but the <NuxtPage /> component is not being used" #30001

Open toboruo opened 4 days ago

toboruo commented 4 days ago

Environment

My machine:

CodeSandbox reproduction:

Reproduction

Demo: https://codesandbox.io/p/devbox/2n7n2z

<template>
  <div>
    <main />
    <Teleport defer to="main">
      <NuxtLayout>
        <NuxtPage />
      </NuxtLayout>
    </Teleport>
  </div>
</template>

Describe the bug

Using the component within a deferred Teleport consistently throws the following warning in the console:

 WARN  [nuxt] Your project has pages but the <NuxtPage /> component has not been used. You might be using the <RouterView /> component instead, which will not work correctly in Nuxt. You can set pages: false in nuxt.config if you do not wish to use the Nuxt vue-router integration.

This does not occur if the Teleport is not deferred, but I need to defer it for my use case. It also does not occur if ssr: false is specified, so I assume the app:rendered and app:suspense:resolve hooks are probably relevant.

Vue lets me suppress the inevitable hydration mismatch warning with <main data-allow-mismatch="children" />, but Nuxt does not let me suppress the warning, so it clutters the console.

Additional context

No response

Logs

cernymatej commented 1 day ago

Just curious—what is your use case exactly for using a deferred teleport for the whole content like this?

toboruo commented 17 hours ago

I need to display a brief and minimal SVG animation before the content is available to the user. As an added bonus the content also seems to load significantly faster doing it this way, while also negating the problems associated with CSS-in-JS for SSR.

cernymatej commented 13 hours ago

Nuxt supports SSR for teleports only to the #teleports target. This means that if you teleport to any other location, the content to be teleported will not appear in the HTML response from the server. Your solution causes a hydration mismatch for the entire content of your app, and I think that ignoring it using data-allow-mismatch is not the best approach.

If you don’t want the entire app to be client-side rendered, I suggest wrapping the teleport in <ClientOnly>—since it isn’t server-side rendered anyway—which will eliminate the warning.


As for checking whether <NuxtPage> has been used when teleporting on the server (to the #teleports target), I wonder if we should move the checkIfPageUnused check to a point further down, perhaps somewhere around here: https://github.com/nuxt/nuxt/blob/edc299a04344897ac110aca3b3a2c2705b0cef35/packages/nuxt/src/core/runtime/nitro/renderer.ts#L519