You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vaadin Flow 23.2自定义Web组件生产环境无法加载求助

问题:Vaadin Flow 23.2自定义Web组件生产环境不加载Shadow DOM

我使用Vaadin Flow 23.2开发了若干Web组件,这些组件在开发环境中运行正常,但部署到生产环境后无法正常工作。最明显的表现是开发环境下组件标签带有Shadow DOM,而生产环境中没有Shadow DOM。需说明的是,这些组件仅在客户端使用,我为每个Web组件都编写了对应的服务端组件,但并未通过服务端组件创建实例,而是通过向浏览器发送原生HTML来渲染组件。

客户端代码

import { css, html, LitElement } from 'lit';
import { property } from 'lit/decorators.js';

export class HintBlock extends LitElement {

    @property()
    colour = 'green';

    static styles = 
        css`
    .red {
        border-left: 4px solid red;
        padding: 10px;
        margin: 10px;
    }
     .green {
        border-left: 4px solid green;
        padding: 10px;
        margin: 10px;
    }
     .blue {
        border-left: 4px solid blue;
        padding: 10px;
        margin: 10px;
    }
    .orange {
        border-left: 4px solid orange;
        padding: 10px;
        margin: 10px;
    }
    `;

    render() {
        return html`
    <div class=${this.colour}>
        <slot></slot>
    </div>
    `;
    }
}
customElements.define('hint-block', HintBlock);

未使用的服务端组件代码

package dev.onepub.components;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;

/**
 * Server side for HintBlock Web Component 
 * @author bsutton
 *
 */

@Tag("hint-block")
@JsModule("./components/hint-block/hint-block.ts")
public class WCHintBlock extends Component {
    
    static Logger logger = LogManager.getLogger();

    private static final long serialVersionUID = 1L;

    public WCHintBlock(String content) {
        this.setContent(content);
    }
    
    private void setContent(String content) {
        getElement().setProperty("content", content);
    }
}

渲染效果对比

  • 开发环境下组件渲染效果:
    开发环境下hint-block渲染效果

  • 生产环境下组件渲染效果:
    生产环境下hint-block渲染效果

疑问:请问是否需要执行额外操作才能让自定义Web组件被包含到生产构建中?我原以为@JsModule和@Tag注解已经足够。


解决方案

问题核心

Vaadin生产构建会启动摇树优化(Tree Shaking),只打包服务端代码实际引用到的前端资源。你虽然给服务端组件加了@JsModule注解,但因为从未实例化过这个服务端组件,Vaadin的构建工具会判定该前端模块未被使用,不会将其打包进生产包。客户端没有加载到Web组件的定义,自然无法创建Shadow DOM,组件也就失效了。

可行解决办法

  1. 强制引入模块
    在项目的主入口类(比如Spring Boot的Application类)或者任何一定会被加载的配置类上,直接添加@JsModule注解引入你的Web组件模块:
@JsModule("./components/hint-block/hint-block.ts")

这样构建工具就会把该模块纳入生产构建范围,不会被摇树优化剔除。

  1. 改用服务端组件实例化
    如果业务允许,放弃直接发送原生HTML的方式,改用服务端组件创建实例。这样Vaadin会自动识别组件依赖,确保前端模块被打包,同时还能获得服务端对组件的状态控制能力。

  2. 手动修改构建配置
    如果使用Maven或Gradle,可以在构建脚本中手动指定要包含的前端资源。不过这种方式需要手动维护资源路径,不如前两种简洁,容易出现路径错误,不推荐优先使用。

补充说明

开发环境下Vaadin会加载所有前端资源(或按需实时加载),所以即使没有显式引用也能正常运行;但生产环境为了优化包体积,会严格剔除未被引用的资源,这就是开发和生产环境表现差异的原因。


内容的提问来源于stack exchange,提问作者Brett Sutton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:25:59