Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should silently fail hydrating empty container in production #4034

Closed
Trinovantes opened this issue Jul 1, 2021 · 3 comments
Closed

Should silently fail hydrating empty container in production #4034

Trinovantes opened this issue Jul 1, 2021 · 3 comments
Labels
has workaround A workaround has been found to avoid the problem scope: ssr

Comments

@Trinovantes
Copy link

What problem does this feature solve?

In my SSG app, I have several html files generated by renderToString (e.g. /index.html, /about/index.html). For all other routes, I would like to fallback to an empty app.html rather than my homepage's /index.html. This prevents my app from temporarily flashing the homepage before routing to the correct components.

# nginx config
server {
    listen      80;
    location / {
        # Exact route match or app.html
        try_files $uri $uri/index.html /app.html;
    }
}
<!-- fallback app.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <script defer="" src="/public/main.js"></script>
</head>
<body>
    <div id="app"></div>
</body>
</html>
// main.js
const app = createSSRApp(App)
app.mount('#app')

This works fine in development but breaks in production due to an Cannot read property 'nodeType' of null error. I think this is due to the early exit guarded by __DEV__ && !container.hasChildNodes() condition:
https://github.com/vuejs/vue-next/blob/b46a4dccf656280f9905e1bdc47022cb01c062c3/packages/runtime-core/src/hydration.ts#L60-L69

What does the proposed API look like?

Instead, I believe it should always full mount when !container.hasChildNodes() and guard the console warning with __DEV__

    if (!container.hasChildNodes()) {
      if (__DEV__) {
        warn(
          `Attempting to hydrate existing markup but container is empty. `  
            `Performing full mount instead.`
        )
      }
      patch(null, vnode, container)
      return
    }
@posva posva added scope: ssr has workaround A workaround has been found to avoid the problem labels Jul 1, 2021
@posva
Copy link
Member

posva commented Jul 1, 2021

You can find multiple workarounds like having one index.html that isn't ssr rendered to avoid doing the hydration. After all, you are purposely hydrating the page with the wrong content

@Trinovantes
Copy link
Author

I'm currently working around this by manually checking IS_SSR || document.querySelector('#id').hasChildNodes() ? createSSRApp(App) : createApp(App)

This is pretty messy and couples the root app creation step with the DOM.

AFAIK, there's no way to disable hydration in the DOM in Vue 3 since createSSRApp always assume it should hydrate. Back in Vue 2, removing data-server-rendered attribute from <div id="app"> is enough to disable hydration.

@terwer
Copy link

terwer commented Apr 23, 2023

Thanks Trinovantes , helps me a lot

@github-actions github-actions bot locked and limited conversation to collaborators Sep 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has workaround A workaround has been found to avoid the problem scope: ssr
Projects
None yet
Development

No branches or pull requests

3 participants