I am building a Vue plugin that works fine when installed via npm but throws an error when imported dynamically via a CDN:Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'ref')
I suspect this issue arises because the plugin is using a different Vue instance than the host application.
Plugin Details
- Vue version in host app: 3.5.13
- Plugin build: Vite with
vue
externalized invite.config.js
:
export default defineConfig({
build: {
lib: {
entry: './src/index.js',
name: 'NoteWriterPlugin',
fileName: (format) => `noteWriter.${format}.js`,
formats: ['es', 'umd'],
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue',
},
},
},
},
});
- Usage: I load the plugin dynamically like this:
import { createApp } from "vue";
import App from "./App.vue";
import loadPluginFromCDN from "./install.js";
const app = createApp(App);
const cdnUrl = "http://127.0.0.1:3000/dist/noteWriter.umd.js";
(async () => {
const plugin = await loadPluginFromCDN(cdnUrl);
if (plugin && typeof plugin.install === "function") {
app.use(plugin);
} else {
console.error("The plugin does not expose a valid 'install' method.");
}
app.mount("#app");
})();
export default async function loadPluginFromCDN(url) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = () => {
// Ensure the global variable matches the name defined in your UMD build
console.log(window.NoteWriterPlugin)
resolve(window.NoteWriterPlugin);
};
script.onerror = () => {
reject(new Error(`Failed to load script: ${url}`));
};
document.head.appendChild(script);
});
}
Debugging Observations
- The plugin exports an install function and appears to load correctly from the CDN:
export default {
install(app) {
const count = ref(0); // Error occurs here
app.provide("count", count);
},
};
- The error suggests that ref is undefined, indicating that the plugin and host app are using different Vue instances.
Steps Taken
- I ensured vue is externalized in the plugin build (external: ['vue']).
- Both the host app and the plugin are using Vue version 3.5.13 (checked via npm list vue).
- When bundled via npm, the plugin works as expected, but loading via CDN results in the error.
Question
How can I ensure that my plugin shares the same Vue instance as the host app when loaded via a CDN? Is there a better way to handle this situation or pass the Vue instance to the plugin dynamically?