Reactive issue in composition API when compiling as library
Vue version
3.2.36
Link to minimal reproduction
https://github.com/jsbr/vue-issue-reactive-composite-api
Steps to reproduce
Try the minimal reproduction project (check the readme)
or:
- Create a simple project with a basic composite api component:
<script setup lang="ts">
import { reactive } from 'vue';
const data = reactive({
count: 0
})
setInterval(()=>data.count++,1000);
</script>
<template>
<h3>Vite Composite Api: {{data.count}}</h3>
</template>
- build it, configure the package.json
- create a second project
- install the previous project into the new one.
- Use the component previously create in the new project:
<script setup lang="ts">
import {CompApiTestVite} from 'test-lib-vite';
</script>
<template>
<CompApiTestVite></CompApiTestVite>
</template>
- npm run serve (for vue-cli) or vite build (for vite.js)
What is expected?
Component should be reactive and increment the counter (in the exemple)
What is actually happening?
Counter don't increment when:
- Component is used in other project in dev and prod for vue-cli
- Component is used in other project and build in prod with vite.js
Counter increment when:
- Executed in the library project
- Executed in dev with vite.js
System Info
System:
OS: Linux 5.10 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
CPU: (12) x64 Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
Binaries:
Node: 16.15.1 - ~/.nvm/versions/node/v16.15.1/bin/node
Yarn: Not Found
npm: 8.11.0 - ~/.nvm/versions/node/v16.15.1/bin/npm
Browsers:
Vivaldi
Chrome: Not Found
Firefox: 101.0.1
npmGlobalPackages:
@vue/cli: Not Found
Any additional comments?
Previously thinking is was a vuecli (see: https://github.com/vuejs/vue-cli/issues/7196) Now found it also happens on vite.js when build in production (vitest build)
When we use Composition Api for a component library and use it in another vue project, the components are no longer reactive.
Event though you externalize vue in the lib folders, it's still existing in those folders' node_modules
.
When you include these projects into the apps via file://...
, the 'vue'
imports in your lib files will import vue from their node_modules
folder, while your app's code will import vue from their node_modules
folder.
So you end up with Vue being included in the app two times, which breaks Vue's singletons used for tracking the currently active component scope etc. This is a local problem, it would not occur if you published your libs to npm and properly installed from the there as real packages.
For vite, the solution would be to use resolve.dedupe: ['vue']
, for webpack/Vue CLI, you would have to create an alias for 'vue$'
resolving to an absolute path.