vuejs / vue-web-component-wrapper

(Vue 2 only) Wrap a Vue component as a web component / custom element.
1.05k stars 100 forks source link

Add support for Vue 3 with web-component-wrapper #93

Open aranoe opened 3 years ago

aranoe commented 3 years ago

I wanted to migrate my Vue 2 project to Vue 3. The problem is, that the wrap-function is still using and expecting the Vue-instance, which is why i get the following error:

vue-wc-wrapper.js?b803:172 Uncaught TypeError: Vue is not a constructor

The main.js:

import { createApp } from "vue";
import App from "./App";
import wrap from "@vue/web-component-wrapper";

const app = createApp(App);

const WrappedElement = wrap(app, app);
// Tried several other things
// const WrappedElement = wrap(app, App);
// const WrappedElement = wrap({}, app);
// const WrappedElement = wrap({}, App);
// const WrappedElement = wrap(app);

window.customElements.define("my-name", WrappedElement);

This makes total sense, since global Vue doesn't exist anymore. Any work around on this?

LinusBorg commented 3 years ago

I started working on the port of the wrapping library, but we also need to add back some capabilities to the Vue-3-compatible versions of vue-loader (& rollup-plugin-vue) in order to be able to inject styles into shadowRoot.

So this is being worked on, but it will still be some time before it's ready.

micru commented 3 years ago

Hi, any news on this? Would be really great to have this abillity

LinusBorg commented 3 years ago

This will still take a while, mostly because we still need to add shaoowRoot CSS injection back into the build tooling. Without that, this lib is pretty useless.

volarname commented 3 years ago

when we can expect vue 3 support? do you have any specific idea? days? weeks? months?

LinusBorg commented 3 years ago

weeks to months. The work I described will take some time and has a bit lower priority at this moment while we get core more stable etc.

sreenaths commented 3 years ago

I have published a Vue3 compatible version of this package @ https://www.npmjs.com/package/vue3-webcomponent-wrapper. It supports reactive attributes, events & slots. Feel free to use it if you are not keen on shadow-root. Also please find a demo app that uses my wrapper @ https://github.com/sreenaths/vue3-webcomponent-wrapper-demo

If you have found an issue with the wrapper, please submit a PR on https://github.com/cloudera/hue/tree/master/desktop/core/src/desktop/js/vue/wrapper

nunofhfontes commented 3 years ago

How can I use router or store on a Vue web component if those should be declared on the main.js file?

DrMabuse23 commented 3 years ago

I have published a Vue3 compatible version of this package @ https://www.npmjs.com/package/vue3-webcomponent-wrapper. It supports reactive attributes, events & slots. Feel free to use it if you are not keen on shadow-root. Also please find a demo app that uses my wrapper @ https://github.com/sreenaths/vue3-webcomponent-wrapper-demo

If you have found an issue with the wrapper, please submit a PR on https://github.com/cloudera/hue/tree/master/desktop/core/src/desktop/js/vue/wrapper

i try the demo and it looks like you dont have a shadow root any plans on that ? @sreenaths

sreenaths commented 3 years ago

@DrMabuse23 Sorry that I don't have immediate plans for shadow root .

sreenaths commented 3 years ago

@nunofhfontes Was that question regarding vue3-webcomponent-wrapper?

fedifazzy commented 3 years ago

How can I use router or store on a Vue web component if those should be declared on the main.js file?

You can use it like this:

const createAppWrapper: CreateAppFunction<Element> = (component) => {
  return createApp(component)
  .use(store)
  .use(router)
}

const webComponent = wrapper(RouterViewWrapper, createAppWrapper, h);
BlahaMarek commented 3 years ago

@sreenaths

how can i publish a component and use it in another project ? not whole app, just one component. thanks

sreenaths commented 3 years ago

@BlahaMarek You could use webpack and build everything into a vanilla javascript file. Publish that file in an NPM package, and load that file in another project using a script tag or import "path/to/file".

For instance following is how we package a er-diagram component.

  1. Wrap the component - https://github.com/cloudera/hue/blob/master/desktop/core/src/desktop/js/components/er-diagram/webcomp.ts
  2. Build the file using webpack - https://github.com/cloudera/hue/blob/master/webpack.config.npm.js#L95
  3. Publish - https://github.com/cloudera/hue/blob/master/package.json#L162
  4. Load using a script tag - https://github.com/cloudera/hue/blob/master/tools/examples/components/er-diagram-demo/index.html#L4

Note: If the other project uses webpack then you could skip the build part all together. Just publish the source as an NPM package and configure the bundler in the other project to bundle everything.

pawel-marciniak commented 3 years ago

Guys, maybe move this discussion about vue3-webcomponent-wrapper package to its repository and keep this issue about official package. Are we have any news about official package? Any progress?

TFohrer commented 3 years ago

@LinusBorg: Do you have any update for us on the Vue 3 support? Currently deciding whether to use Vue 2 or Vue 3 for a project where we we will create web-components. Thanks the response and of course your work.

odai-alali commented 3 years ago

@TFohrer I would recommend you to start with Vue2 and @vue/composition-api and put Vue3 on hold for now. It's working, it's great and all that, but it's not ready for production use. Besides the web component wrapper, Test-utils and DevTools still have work to be done. There is a fork for the wrapper that works with Vue3, but @vue/composition-api is really good and would serve as an in between steps toward Vue3. You can even utilize @vue/component-api as an alternative to Vuex (IMHO you do not need vuex with vue3, as long as the Vuex DevTools are not critical to you).

When Vue3 is production ready, all you need to do is to replace "@vue/composition-api" with "vue" in your imports and you are good to go.

TatsuyaYamamoto commented 3 years ago

@LinusBorg I'm sorry to mention you suddenly. I opened a draft PR (#109) to provide Vue3 users the same function as the current wrap() for Vue2.

I want you to check it if you have time 🙏

sherlock1982 commented 3 years ago

@TatsuyaYamamoto I tried your repository and got this for v3 (vue3-webcomponent-wrapper works for me but no shadowDom, no styles):

Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
LinusBorg commented 3 years ago

Vue 3 will have built-in support for web component wrappers in 3.2. you can already test it in the current beta.

LinusBorg commented 3 years ago

Documentation will come with the stable release.

Guessing what you did wrong: defineCustomElement() expects a compiled component

So You don't replace defineComponent in an SFC. You import an SFC, then wrap it:

import MyComponent from './MyComponent.vue'

const myWebComponent = defineCustomElement(MyComponent)

customElements.define('my-web-component', myWebComponent)
sherlock1982 commented 3 years ago

Thanks a lot! I also found a tweet about it. Tried it and looks working. The only thing missing so far is that it doesn't add