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

configureApp for defineCustomElement Not Executed for Async Components #12448

Open
farcry550 opened this issue Nov 20, 2024 · 2 comments
Open
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. has workaround A workaround has been found to avoid the problem scope: custom elements

Comments

@farcry550
Copy link

farcry550 commented Nov 20, 2024

Vue version

3.5.12

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-b9enev?file=src%2Fmain.js

Steps to reproduce

  1. Open the link to the reproduction
  2. Observe app-injected not displayed in the preview

What is expected?

When given an async component, defineCustomElement with the configureApp option results in configureApp being called on the loaded component's mount.

What is actually happening?

When given an async component, defineCustomElement with the configureApp option does not result in configureApp being called on the loaded component's mount.

System Info

System:
    OS: Linux 5.15 Debian GNU/Linux 10 (buster) 10 (buster)
    CPU: (8) x64 Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz
    Memory: 1.41 GB / 7.76 GB
    Container: Yes
    Shell: 5.0.3 - /bin/bash
  Binaries:
    Node: 16.20.2 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 8.19.4 - /usr/local/bin/npm
  npmPackages:
    vue: ^3.5.12 => 3.5.12

Any additional comments?

When resolving an async component, the component's loader is called and the loaded component is resolved.

const asyncDef = (this._def as ComponentOptions).__asyncLoader
if (asyncDef) {
this._pendingResolve = asyncDef().then(def =>
resolve((this._def = def), true),
)
} else {
resolve(this._def)
}

However, the configureApp function is attached to the async wrapper. When the component is loaded and the wrapper is discarded, configureApp is discarded as well. Thus when the component is mounted, configureApp is not called.

private _mount(def: InnerComponentDef) {
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {
// @ts-expect-error
def.name = 'VueElement'
}
this._app = this._createApp(def)
if (def.configureApp) {
def.configureApp(this._app)
}
this._app._ceVNode = this._createVNode()
this._app.mount(this._root)

A fix here may be to assign the function from the wrapper to the loaded component before reassignment of this._def.

const asyncDef = this._def.__asyncLoader;
if (asyncDef) {
  this._pendingResolve = asyncDef().then(
    (def) => {
      if (this._def.configureApp) {
        def.configureApp = this._def.configureApp;
      }
      resolve(this._def = def, true);
    }
  );
} else {
  resolve(this._def);
}

An interesting workaround is to move configureApp into the component's options as shown by this repro. I'm not sure if this is intentional or of the repercussions.

@edison1105 edison1105 added has workaround A workaround has been found to avoid the problem 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: custom elements labels Nov 21, 2024
@edison1105
Copy link
Member

edison1105 commented Nov 21, 2024

@farcry550
Nice, You've found the root cause of the problem.
PR welcome!

An interesting workaround is to move configureApp into the component's options as shown by this repro. I'm not sure if this is intentional or of the repercussions.

This is a hidden usage, and it's correct.

if (isPlainObject(Comp)) extend(Comp, extraOptions)

Ultimately, configureApp will be merged into def

@farcry550
Copy link
Author

PR welcome!

I’ll create one!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. has workaround A workaround has been found to avoid the problem scope: custom elements
Projects
None yet
Development

No branches or pull requests

2 participants