I tried to create my application basics as a npm library with vite, vue, vuetify and pinia.
So.... I created a simple vue@latest project and modified the package.json and vite.config.ts.
In my library the package.json
{
"name": "my-lib",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "./dist/my-lib.cjs.js",
"module": "./dist/my-lib.es.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.cjs.js",
"types": "./dist/types/index.d.ts"
},
"./components": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.cjs.js",
"types": "./dist/types/index.d.ts"
}
},
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" -- && run-p build-types",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"build-types": "vue-tsc -p tsconfig.lib.json --composite false --emitDeclarationOnly",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"pinia": "^2.1.7",
"vue": "^3.3.4",
"vue-router": "^4.2.5",
"vuetify": "^3.3.23"
},
"devDependencies": {
"@babel/types": "^7.23.0",
"@types/jsdom": "^21.1.3",
"jsdom": "^22.1.0",
"@rushstack/eslint-patch": "^1.3.3",
"@tsconfig/node18": "^18.2.2",
"@types/node": "^18.18.5",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"npm-run-all2": "^6.1.1",
"prettier": "^3.0.3",
"typescript": "~5.2.0",
"vite": "^4.4.11",
"vue-tsc": "^1.8.19"
}
}
and my vite.config.ts:
import {fileURLToPath, URL} from 'node:url'
import {resolve} from "path"
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
build: {
sourcemap: true,
lib: {
name: 'my-lib',
entry: {
'my-lib': resolve(__dirname, 'src/index.ts'),
'components': resolve(__dirname, 'src/components/index.ts'),
'stores': resolve(__dirname, 'src/stores/index.ts'),
},
fileName: (fmt, name) => `${name}.${fmt}.js`,
},
rollupOptions: {
external: ['vue', 'pinia', 'vue-router', 'axios', 'vue-i18n', 'vuetify', '@vueuse/core'],
output: {
globals: {
vue: 'Vue',
},
}
}
},
plugins: [vue()],
resolve: {
alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}
}
})
created component is exported in the lib with the store
import type {App} from 'vue'
import CounterButton from './components/CounterButton.vue';
import {useCounterStore} from './stores/counter'
function install(app: App) {
app.component('CounterButton', CounterButton)
}
export default install
export {CounterButton, useCounterStore}
the component is really simple
<script lang="ts" setup>
import {useCounterStore} from "@/stores/counter";
const counterStore = useCounterStore();
</script>
<template>
<v-btn :text="'count of ' + counterStore.count" @click="counterStore.increment()"/>
</template>
That seems to work, great. Then I created a second vue@latest project, ran npm link ../my-lib
in this one use the store and component from my library.
<script lang="ts" setup>
import {CounterButton, useCounterStore} from "my-lib"
import {storeToRefs} from "pinia";
const counterStore = useCounterStore();
const {count} = storeToRefs(counterStore)
</script>
<template>
<main>
<div>
<CounterButton/>
</div>
<div>Current Counter: {{ count }}</div>
</main>
</template>
All works fine when running with npm run dev
but when using npm run build && npm run preview
I'm getting a runtime error on the page
TypeError: Cannot read properties of undefined (reading '_s')
at i (pinia.mjs:1714:20)
at setup (HomeView.vue:5:22)
at Tn (runtime-core.esm-bundler.js:158:18)
at ag (runtime-core.esm-bundler.js:7290:25)
at lg (runtime-core.esm-bundler.js:7251:36)
at j (runtime-core.esm-bundler.js:5647:7)
at O (runtime-core.esm-bundler.js:5613:9)
at g (runtime-core.esm-bundler.js:5088:11)
at ws.te [as fn] (runtime-core.esm-bundler.js:5821:9)
at ws.run (reactivity.esm-bundler.js:178:19)
It seems that the lib can't access the pinia instance when it is built. pinia.mjs
...
pinia = activePinia;
if (!pinia._s.has(id)) {
// creating the store registers it in `pinia._s`
if (isSetupStore) {
createSetupStore(id, setup, options, pinia);
}
else {
createOptionsStore(id, options, pinia);
}
/* istanbul ignore else */
if ((process.env.NODE_ENV !== 'production')) {
// @ts-expect-error: not the right inferred type
useStore._pinia = pinia;
}
}
...
Does anyone have a hint as to what my error is?
You can find my sample project on Github
You can use vite's shared options resolve.dedupe to resolve this issue
import { defineConfig } from 'vite'
export default defineConfig(() => {
return {
// ...
resolve: {
dedupe: ['pinia'],
},
// ...
}
})