vue-web-component-wrapper icon indicating copy to clipboard operation
vue-web-component-wrapper copied to clipboard

Async setup possible?

Open khrise opened this issue 1 year ago • 13 comments

In my original app, I have an async setup. Among other async stuff, a configuration is fetched from a remote server.

loadConfig().then(() => {
  const app = createApp(App);
  app
   .use(...)
   .use(...)
   .mount('#app')
});

Is there a way to accomplish this with vue-web-component-wrapper? Basically, I'd like to be able to make "createApp" wait for an arbitrary (configurable) promise. Thanks!

khrise avatar Jul 02 '24 08:07 khrise

Hi @khrise, Interesting use case, I would suggest to try use the createWebComponent in the loadConfig().then(() => {

maybe something like this

loadConfig().then(() => {
createWebComponent({
  rootComponent: app,
  elementName: 'my-web-component',
  plugins: pluginsWrapper,
  cssFrameworkStyles: style,
  VueDefineCustomElement,
  h,
  createApp,
  getCurrentInstance,
})
});

EranGrin avatar Jul 02 '24 18:07 EranGrin

Hi @EranGrin, I have a similar question, but concerning vue-router. My original code is:

const app = createApp(App);

app.use(router);
...

router.isReady().then(() => {
  app.mount('#app');
});

I don't know how to add the router.isReady()... code to the pluginsWrapper object.

The problem that this piece of code solves is described here: Vue Router 4: Route Params Not Available on Created/Setup Also described here: All navigations are now always asynchronous

Thank you!

tbl0605 avatar Jul 07 '24 17:07 tbl0605

Hi @tbl0605,

Could you please provide more details about your use case? It appears to be an edge case that the current plugin configuration does not support. Understanding your specific requirements better will help me assess the feasibility of incorporating this feature. Alternatively, you are welcome to contribute by opening a pull request for this feature.

Thanks

EranGrin avatar Jul 08 '24 11:07 EranGrin

Hi @EranGrin, thank you for your fast answer! :)

Could you please provide more details about your use case?

I have a Vue application (that I would like to convert to a web component) that contains <router-links> with query parameters. The users like to open each link in separate navigator tabs (by right-clicking on them and doing "Open the link in a new tab"), so they are able to use different pages of the application "at same time".

Without the router.isReady() hack, I loose the query informations at the startup of the new application instance in the new tab. It's really like the problem described here: Vue Router 4: Route Params Not Available on Created/Setup

router.isReady() is also needed to solve another kind of "page refresh" problem explained here.

Alternatively, you are welcome to contribute by opening a pull request for this feature.

Frankly, I have no idea how to fix this in your code :/ Ideally there should be some asynchronous callback somewhere so I could do await router.isReady() inside it, but can this really be implemented on your side to delay the web component mounting?

tbl0605 avatar Jul 08 '24 17:07 tbl0605

I was working on the async solution, but I noticed that for the query param it is not needed, meaning it seems to work without any changes. Could you please check?

EranGrin avatar Jul 10 '24 19:07 EranGrin

H @EranGrin, from my few tests lately, you're right it seems router.isReady() is not needed. I'm a little surprised though. I hope I'm not wrong in my assumptions ^^

tbl0605 avatar Jul 14 '24 16:07 tbl0605

Great, I'm still planning to introduce the asnyc feature but I think that for your use case this isn't needed

EranGrin avatar Jul 15 '24 05:07 EranGrin

@khrise Is the asnyc feature still interesting to you? Would you be able to test it?

EranGrin avatar Jul 15 '24 05:07 EranGrin

@khrise Is the asnyc feature still interesting to you? Would you be able to test it?

Oh yes, and yes. Sorry, I've been busy in other projects the last few days. I tried your suggestion from your first answer above, but it didn't seem to do the trick. (Although I don't exactly understand why not).

EDIT: No, it does work, apparently. I had another call outside the promise lambda :/

khrise avatar Jul 15 '24 07:07 khrise

@khrise if I understand you correctly, this solution does work, and we can close this ticket, right?

loadConfig().then(() => {
createWebComponent({

EranGrin avatar Jul 18 '24 07:07 EranGrin

Yes, we can close this. I think it's not the most intuitive way to solve this, because to me, this appears like "load the config, then register the web component(s)", while what I actually want is "register the web component(s), and when bootstrapping one of them, load the config before firing up the app". (Does that make sense?) In fact, I think it's two different use cases. For my use case, your proposed solution is fine. (I guess, I'm still exploring.) Thanks!

khrise avatar Jul 18 '24 07:07 khrise

I have worked on a solution that might give better support for async initialization

https://github.com/EranGrin/vue-web-component-wrapper/compare/main...feature/init-promise

which let one pass a promise to the plugin

createWebComponent({
  rootComponent: app,
  elementName: 'my-web-component',
  plugins: pluginsWrapper,
  cssFrameworkStyles: style,
  VueDefineCustomElement,
  h,
  createApp,
  getCurrentInstance,
  asyncInitialization: () => new Promise((res) => setTimeout(() => res("p1"), 1000))
}) 

but I am still not quite sure regarding this solution and the related use-cases

EranGrin avatar Jul 18 '24 09:07 EranGrin

I have worked on a solution that might give better support for async initialization

main...feature/init-promise

which let one pass a promise to the plugin

createWebComponent({
  rootComponent: app,
  elementName: 'my-web-component',
  plugins: pluginsWrapper,
  cssFrameworkStyles: style,
  VueDefineCustomElement,
  h,
  createApp,
  getCurrentInstance,
  asyncInitialization: () => new Promise((res) => setTimeout(() => res("p1"), 1000))
}) 

but I am still not quite sure regarding this solution and the related use-cases

That's pretty much what I had in mind in the first place.

khrise avatar Jul 18 '24 09:07 khrise

I'm also interested in async setup. My use case is that I might have multiple components on the same page but each component has different props and I need to use the props to get some configs from a server before i spin up the App.vue.

So optimally I'd be able to get the props, do some async requests, and feed these results into the plugins install method before the app starts.

Pretagonist avatar Jan 21 '25 09:01 Pretagonist

Finally, I could find time to add support for this feature. I introduced three new features to support async initialization.

  • Async Initialization: Option to delay the initialization until its Promise resolves.
  • Loader Support: Support for loader spinner elements until the application is fully initialized.
  • Hide slot content until the component is fully mounted: Option to hide the content of named slots until the web-component is fully mounted.

Below is an example of a demo app with all of these new features. https://github.com/EranGrin/vue-web-component-wrapper/tree/main/demo-app-vite

@Pretagonist @khrise let me know if you find time to run some tests

EranGrin avatar Feb 10 '25 17:02 EranGrin

The feature is available in the last version

EranGrin avatar Mar 22 '25 14:03 EranGrin