[Vue3] Lost reactivity with composition api (in vue-cli)

Hey folks :slight_smile:

I’m having a problem with reactivity in one of my projects. I have a main project and want to dynamically add another project/component into my main project (writing a simple plugin system).
This is what my simple counter plugin component looks like (both as composition api and options api component):

My main project is based on Laravel and Laravel Mix as build tool. Everything works fine there.

For my plugin I used vue-cli to setup a new project and vue-cli-service as build tool.
When I build that component and want to use it in my other project I lose reactivity in that component.
I already tried a lot of webpack configs and other fixes, but nothing worked. I then decided to write that component using options api instead of composition api and surprisingly that worked just fine! :tada:

My question now is what I could have done wrong with composition api or if this is a (known) bug in vue-cli or external components using composition api in general?

I know now what the (obvious) problem is. The line import {reactive} from 'vue'; in the plugin referes to a different vue as in my main app.

I tried several solutions I found online, but they didn’t work for me.
First solution was to add vue to devDependencies and to peerDependenciesin the plugin, but that didn’t work, at least with my setup.
Second solution was to add vue to externals in webpack config (I added it to vue.config.js) like this:

module.exports = {
    chainWebpack: config => {
        config.externals({
            ...config.get('externals'),
            vue: 'vue',
        });
    },
}

Unfortunately, this didn’t work either.

Does anyone has an idea what I did wrong?

This isn’t your issue. Importing reactive is just accessing the reactive function, it has nothing to do with the scope of your app instance.

Can you elaborate on this? How are you building your plugins/components you want to use in other projects? How are you exporting and importing them between projects?

Thanks for your reply!

Good to know. That’s what I read a couple of times in several forums and it made sense to me.

Of course, sorry I left that part out…
The plugin is build using vue-cli-service as configured in the sandbox in OP (vue-cli-service build). I also tried different parameters (vue-cli-service build --target lib --name counter ./src/main.js --mode production).
The resulting js file is than copied to the public folder of my main (Laravel) app and loaded in the body of my layout file (after all other scripts)

<body>
    <div id="app" class="d-flex flex-column"></div>

    <!-- Scripts -->
    <script src="js/manifest.js"></script>
    <script src="js/vendor.js"></script>
    <script src="js/app.js"></script>
    <script src="js/counter.js"></script>
</body>

This loaded script counter.js then calls the window.$pluginSystem.createPlugin function provided by my main app.
In that function I simply call

createPlugin = (data) => {
window.$pluginSystem.vueApp.component(data.component.name, data.component);
}

The main app is build using Laravel Mix with the following config:

// webpack.mix.js
mix.js('resources/js/app.js', 'public/js').vue().extract();

// babel.config.js (same as in plugin)
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}