Vue-cli: Store not working in web components

Created on 21 Aug 2018  Β·  19Comments  Β·  Source: vuejs/vue-cli

Version

3.0.1

image

Node and OS info

node 10.7.0 / npm 6.3.0

Steps to reproduce

– Go to vue-cli GUI
– create new project (vuex, babel, less-css, no typescript)
– make a simple state in vuex: foo: "bar"
– make it a getter aswell
– go to App.vue
– import mapGetters from vuex
– use mapGetters in computed to get the foo value
– use it in the App.vue template: This is foo: {{ foo }}
– build a web component named: my-component
– open demo.html in a browser

What is expected?

No error

What is actually happening?

Error in console regarding the store :(


Without the store, webcomponents seem to work fine

Most helpful comment

A web component is a library, conceptually.

So its entry point is not main.js, but an entry-wc.js file generated here: https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/commands/build/resolveWcEntry.js

So to use vuex in web component target, you need to initialize the store in App.vue:

import store from './store'

// ...

export default {
  store,
  name: 'app',
  // ...
}

All 19 comments

What's the error in the console?

omg, sorry for the missing error information. I edited the main post

It looks like vuex is not registered correctly. Is your main.js contains those lines? :

  • import VueRouter from 'vue-router'
  • Vue.use(VueRouter)

Also can you profide a reproduction repo please? It will easier for us to help you πŸ™‚

You are talking about VueRouter; did you just misspoke or do you actually mean the router? Because in my setup vuerouter doesn't play in :)

The main.js looks like this:

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

I am facing the issue with a freshly created vue-cli project.
That's why I think the best is you create a fresh one yourself with the settings layed out in "steps to reproduce", don't you think? This way we surely ruled out it has anything to do with my doing / my code.

Oh damn, I always confound vuex and vue-router 😒

I will check on my side

Question not reagarding the bug:
When I got the webcomponent working, could I call a function from outside the console?
Following usecase: I make a webapp which is served as a modal; and the modal should be openable from many different buttons throughout the site. The easiest would be to do something like this:

document.querySelector('my-configurator').modalOpen()

(or some other way to trigger internal methods from the Wecomponent)

I made a reproduction repo here: https://github.com/Kocal/vue-cli-web-components-store

I confirm that building for web app (vue-cli-service build --mode production --dest dist --target app) works fine, but building for web component (vue-cli-service build --mode production --dest dist --target wc --name my-component) fails.

Sorry, I don't know enough about web components, I can't help you more πŸ€·β€β™‚οΈ

Just to clear out possible misunderstandings:

The actual building process is successful for me; since 3.0.0rc13, where a --name bug was fixed, the actual building step works.

So building the webcomponent, both WITH and WITHOUT a store, seems to work.

The store-less version also works in the browser and correctly displays the app,
whereas the store version breaks with the mentioned error and displays nothing.

Yea sorry, when I mean "it works fine" and "it fails", I actually mean that app (always with store) is displayed when targeting web app, and is not displayed when targeting web component.

I look like Vue.use(Vuex) is not executed, or maybe there is a problem with vue-web-component-wrapper... πŸ€”

Vue.use(Vuex) is inside the store.js by default; that's correct, right?

Yep

A web component is a library, conceptually.

So its entry point is not main.js, but an entry-wc.js file generated here: https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-service/lib/commands/build/resolveWcEntry.js

So to use vuex in web component target, you need to initialize the store in App.vue:

import store from './store'

// ...

export default {
  store,
  name: 'app',
  // ...
}

It works! Both in a webcomponent and a library as target.

tenor-1

Thank god you people are faster than an ambulance–

no way I would've figured that out without your help.

Just to be sure now @sodatea
Will it become a problem when I leave the "global declaration" of the store both in the main.js AND the App.vue? Right now it is working on the localhost:8080 served page with a store declaration in BOTH files.

But I'm afraid this is not a good idea.
Would be cool to leave it in both, though, because the app will be shipped as a single SPA and a Library/Webcomponent aswell.

PS: is this behaviour documented somewhere? I'm so overworked I probably wouldn't have found it anyways; but this is definitely worth a notice somewhere.

It's ok to leave it in both.

  1. store.js will execute only once;
  2. store injection works fine for this kind of usage, as you can tell from vuex source code:
    https://github.com/vuejs/vuex/blob/dev/src/mixin.js#L22

Nice! +1
I can't find anything regarding vuex when building a library or webcomponent.
How about putting this as a notice on the build targets page?
https://cli.vuejs.org/guide/build-targets.html

PRs are welcome πŸ˜€

You entrust me, the one struggling with the terminology and concepts behind it, to alter / enhance the official documentation?

tumblr_njzrzaicmg1s3h43ko1_500

what is different about projects created using Vue CLI 3.0 that this extra step is now required?

From the Vuex docs:

When using a module system, it requires importing the store in every component that uses store state, and also requires mocking when testing the component.

Vuex provides a mechanism to "inject" the store into all child components from the root component with the store option (enabled by Vue.use(Vuex)):

Is this somehow possible to set up with a library build target? In lib mode, Vue is externalized, so we can't rely on new Vue({ store, ... }).

Was this page helpful?
0 / 5 - 0 ratings