使用Vaadin导出Web组件并排除共享元素(Vite环境)
问题描述
我通过Vaadin的WebComponentExporter成功将Vaadin视图导出为Web组件,可访问http://localhost:8080/web-component/my-vaadin-view.js。但将该Web组件嵌入另一个Vaadin应用时,出现以下错误:
caught (in promise) DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "vaadin-big-decimal-field" has already been used with this registry at window.customElements.define (http://localhost:8080/languages/Kotlin:6:829) at http://localhost:8081/VAADIN/generated/jar-resources/vaadin-big-decimal-field.js:74:20
已知这类问题可通过bundle方案解决:Web组件在浏览器中只能定义一次,需让bundle模块包含所有使用的组件,其他应用模块排除这些组件。但当前Vaadin使用Vite而非Webpack,该如何实现?
Vite环境下的解决方案
1. 构建包含所有依赖的Web组件Bundle
在导出Web组件的项目中,配置Vite生成独立bundle,把所有依赖的Vaadin组件打包进去:
- 编辑项目的
vite.config.ts,添加库模式构建配置,指定Web组件入口文件,确保所有依赖组件都被打包:
import { defineConfig } from 'vite'; import vaadin from '@vaadin/vite-plugin'; export default defineConfig({ plugins: [vaadin()], build: { lib: { entry: './src/main/webapp/web-component/my-vaadin-view.js', name: 'MyVaadinView', fileName: (format) => `my-vaadin-view.${format}.js` }, rollupOptions: { external: [], // 不排除任何依赖,全部打包进bundle output: { globals: {} // 按需配置全局变量,避免命名冲突 } } } });
- 执行
npm run build生成bundle文件,使用输出的my-vaadin-view.umd.js(或适配的格式)作为独立Web组件资源。
2. 在嵌入应用中排除重复组件
在需要嵌入Web组件的Vaadin应用中,配置Vite排除已包含在bundle中的组件,避免重复注册:
- 修改应用的
vite.config.ts,通过Vaadin插件的exclude选项指定要排除的组件:
import { defineConfig } from 'vite'; import vaadin from '@vaadin/vite-plugin'; export default defineConfig({ plugins: [vaadin({ exclude: [ '@vaadin/big-decimal-field' // 补充所有bundle中已包含的Vaadin组件包名 ] })] });
- 嵌入Web组件时,仅引入打包好的bundle文件,不要单独引入任何依赖组件的JS资源。
3. 增加重复注册防护(可选)
在Web组件bundle的入口文件中添加检测逻辑,避免意外重复注册:
// 以vaadin-big-decimal-field为例 if (!customElements.get('vaadin-big-decimal-field')) { // 原组件注册代码 }
内容的提问来源于stack exchange,提问作者Thomas Uhrig
相关产品推荐
相关产品推荐

