Vue version
3.5.12
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-kennhm?file=src%2FApp.ce.vue
Steps to reproduce
- Open the reproduction link
- Remove the comment in
App.ce.vue after the app is running
If you create a custom element with defineCustomElement and provide something in the app via configureApp the provided context gets lost when a HMR occurs.
What is expected?
The provide context should be kept
What is actually happening?
The provide context will be lost
System Info
No response
Any additional comments?
This is happening because when the custom element will be mounted a VNode will be created that will be linked to the app via _ceVNode (see
|
this._app._ceVNode = this._createVNode() |
). But when a HMR occurs a new VNode will be created (see
|
render(this._createVNode(), this._root) |
) which isn't linked to the app anymore and doesn't have its context.
A possible solution would be to link the newly created VNode with the app or to not create a new VNode on every HMR.
Here is a snippet of a custom definition of defineCustomElement which I did which worked for me:
const vnode = createVNode(AppComponent, this._props);
// @ts-expect-error: Isn't typed
vnode.ce = (instance: ComponentInternalInstance) => {
// @ts-expect-error: Isn't typed
instance.ceReload = (newStyles: string[] | undefined) => {
styleElements.forEach((styleElement) => {
this._shadowRoot?.removeChild(styleElement);
});
styleElements =
newStyles?.map((style) => {
const styleElement = document.createElement("style");
styleElement.textContent = style;
this._shadowRoot?.appendChild(styleElement);
return styleElement;
}) ?? [];
};
instance.emit = (event: string, ...args: unknown[]) => {
this.dispatchEvent(new CustomEvent(event, { detail: args }));
};
};
this._app = createApp(vnode);
this._def.configureApp(this._app);
this._app.mount(rootContainer);
There you first create a VNode with the component and then create the app with the vnode. This way you can set the ce property on the VNode and don't have to create one on every HMR
Vue version
3.5.12
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-kennhm?file=src%2FApp.ce.vue
Steps to reproduce
App.ce.vueafter the app is runningIf you create a custom element with
defineCustomElementand provide something in the app viaconfigureAppthe provided context gets lost when a HMR occurs.What is expected?
The provide context should be kept
What is actually happening?
The provide context will be lost
System Info
No response
Any additional comments?
This is happening because when the custom element will be mounted a VNode will be created that will be linked to the app via
_ceVNode(seecore/packages/runtime-dom/src/apiCustomElement.ts
Line 423 in 06310e8
core/packages/runtime-dom/src/apiCustomElement.ts
Line 523 in 06310e8
A possible solution would be to link the newly created VNode with the app or to not create a new VNode on every HMR.
Here is a snippet of a custom definition of
defineCustomElementwhich I did which worked for me:There you first create a VNode with the component and then create the app with the vnode. This way you can set the
ceproperty on the VNode and don't have to create one on every HMR