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 · 2 comments
Closed

Should silently fail hydrating empty container in production #4034

Trinovantes opened this issue Jul 1, 2021 · 2 comments

Comments

@Trinovantes
Copy link

@Trinovantes Trinovantes commented Jul 1, 2021

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:

if (__DEV__ && !container.hasChildNodes()) {
warn(
`Attempting to hydrate existing markup but container is empty. ` +
`Performing full mount instead.`
)
patch(null, vnode, container)
return
}
hasMismatch = false
hydrateNode(container.firstChild!, vnode, null, null, null)

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
Copy link
Member

@posva 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

@Trinovantes Trinovantes commented Jul 1, 2021

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.

@yyx990803 yyx990803 closed this in 33708e8 Jul 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants