Open CyberAP opened 4 years ago
I think most of those who use SSR use the ClientOnly component (same as Nuxt) and they are using this implementation
// https://github.com/frandiox/vite-ssr/blob/master/src/vue/components.ts
export const ClientOnly = defineComponent({
name: 'ClientOnly',
setup(_, { slots }) {
const show = ref(false)
onMounted(() => {
show.value = true
})
return () => (show.value && slots.default ? slots.default() : null)
},
})
This feature is needed on these components too.
Here is what I tried to do:
// ClientOnly.ts
import { onMounted, defineComponent } from 'vue';
function onAfterHydration (fn: () => void) {
if (typeof window === 'undefined') return;
// @ts-ignore this is for checking if application is already mounted or not
return document.querySelector('#app')?.__vue_app__ ? fn() : onMounted(fn);
}
export default defineComponent({
setup (_, { slots }) {
const show = ref(false);
onAfterHydration(() => {
show.value = true;
});
return () => (show.value && slots.default ? slots.default() : (slots.placeholder ? slots.placeholder() : null));
},
});
What problem does this feature solve?
When an app is server rendered there is a case when server side state does not correspond to client side state on an init lifecycle. Take for example a
window.matchMedia
and conditional rendering depending on matching media queries, the actual media query matching happens after thecreated
stage either onbeforeMount
ormounted
.If you take the
mounted
approach the downside is that client side rendered applications would also be forced into this mode of re-rendering after the initial render because there's no reliable way (at least that I am aware of) to detect that this component is being hydrated. With abeforeMount
approach you'll certainly get hydration errors in production, which is a no go.As a workaround your component can accept a prop like
ssr
or check for common SSR solutions presence like nuxt. Doing this for every isomorphic Vue library feels like a barrier for developers who want to support both client and server side rendering.What does the proposed API look like?
Would it be possible to add a property on a component instance to indicate that in fact this component has hydration undergoing to make an informed decision what state update strategy to take?