Error when unmounting after ssr if async component not loaded yet
Version
3.1.0-beta.3
Reproduction link
https://github.com/danelowe/vite-ssr-lazy-component
Steps to reproduce
- Clone reproducer.
- Run
npm run dev
- Load the index page in browser directly from ssr (i,e, refresh on /)
- Navigate to about page
What is expected?
Displays the about page with no error
What is actually happening?
Error:
Uncaught (in promise) TypeError: instance is null
unmountComponent runtime-core.esm-bundler.js:4818
unmount runtime-core.esm-bundler.js:4736
unmountChildren runtime-core.esm-bundler.js:4864
unmount runtime-core.esm-bundler.js:4754
unmountComponent runtime-core.esm-bundler.js:4835
unmount runtime-core.esm-bundler.js:4736
resolve runtime-core.esm-bundler.js:1328
registerDep runtime-core.esm-bundler.js:1452
promise callback*registerDep runtime-core.esm-bundler.js:1414
mountComponent runtime-core.esm-bundler.js:4213
processComponent runtime-core.esm-bundler.js:4182
In. 3.1.0-beta.3
Uncaught (in promise) TypeError: vnode is null
unmount runtime-core.esm-bundler.js:5619
unmountComponent runtime-core.esm-bundler.js:5733
unmount runtime-core.esm-bundler.js:5634
unmountChildren runtime-core.esm-bundler.js:5762
unmount runtime-core.esm-bundler.js:5652
unmountComponent runtime-core.esm-bundler.js:5733
unmount runtime-core.esm-bundler.js:5634
resolve runtime-core.esm-bundler.js:1672
registerDep runtime-core.esm-bundler.js:1796
I took the example at https://github.com/vitejs/vite/tree/main/packages/playground/ssr-vue
, removed the dep-import-type
dependency, added vite
as a dependency. then modified the import of the Foo
component to chain it's loading to an unresolved promise when rendering client-side.
The intention is to lazy-load/hydrate some components client-side, so any tips on how to achieve this would be appreciated.
In any case, I think this is a significant bug as it would cause errors when navigating before components are able to be loaded.
This is a minimized repro:
const AsyncComp = defineAsyncComponent(() => new Promise((r) => {}))
const CompA = defineComponent({
render: () => h(AsyncComp)
})
const CompB = defineComponent({
render: () => 'foo'
})
createSSRApp({
setup() {
const comp = shallowRef(CompA)
return () => {
return [
h(comp.value),
h('button', { onClick() { comp.value = CompB } }, 'click me')
]
}
}
}).mount('#app')
Use the following html as server-side rendering content
<div id="app"><!--[--><div></div><button>click</button><!--]--></div>