Vue3+Vite嵌入组件:如何封装内置Vue避免冲突?
问题描述
我用Vue 3和Vite开发一款可嵌入的Widget组件,打算通过Vue的defineCustomElement特性实现。相关代码如下:
widget.js 文件
import { createApp, defineCustomElement } from "vue"; import Widget from "./components/Widget.ce.vue"; const TestWidget = defineCustomElement(Widget); customElements.define("test-widget", TestWidget);
vite.config.js 文件
import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ build: { rollupOptions: { input: { widget: "resources/js/widget.js", }, output: { entryFileNames: `assets/[name].js`, chunkFileNames: `assets/[name].js`, assetFileNames: `assets/[name].[ext]`, }, }, }, });
把widget.js引入其他网站,加个<test-widget />标签就能正常跑,但如果那个网站本身已经引入了Vue包,就会出现一堆JS错误。能不能把组件内置的Vue封装起来,避免冲突?
解决方案
当然可以,核心就是让你的Widget用独立的Vue实例,不跟宿主网站的Vue共享全局作用域。具体操作步骤:
1. 配置Vite让Vue打包进Widget并启用沙箱
修改vite.config.js,调整Vue插件和Rollup构建配置,确保Vue被打包进Widget文件,且运行在沙箱里:
import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ vue({ customElement: true, template: { compilerOptions: { // 标记自己的自定义元素,避免Vue编译报错 isCustomElement: tag => tag === 'test-widget' } } }), laravel() ], build: { rollupOptions: { input: { widget: "resources/js/widget.js", }, output: { entryFileNames: `assets/[name].js`, chunkFileNames: `assets/[name].js`, assetFileNames: `assets/[name].[ext]`, }, // 不要把Vue设为外部依赖,强制打包进Widget external: [] }, // 禁用模块预加载,避免依赖宿主环境 modulePreload: { polyfill: false } }, resolve: { // 指定使用Vue的ESM打包版本,确保完全独立 alias: { 'vue': 'vue/dist/vue.runtime.esm-bundler.js' } } });
2. 调整Widget入口文件,移除全局Vue依赖
修改widget.js,去掉不必要的createApp,只保留自定义元素注册逻辑,同时避免重复注册:
import { defineCustomElement } from "vue"; import Widget from "./components/Widget.ce.vue"; const TestWidget = defineCustomElement(Widget); // 先检查元素是否已注册,防止重复定义报错 if (!customElements.get('test-widget')) { customElements.define("test-widget", TestWidget); }
3. 验证效果
构建完成后,打开生成的widget.js,如果里面包含了Vue的runtime代码,就说明配置成功了。这时你的Widget会在自己的隔离环境里运行,不管宿主网站有没有Vue,都不会产生冲突。
内容的提问来源于stack exchange,提问作者Pennywise96
相关产品推荐
相关产品推荐

