Vaadin 24 upgrade from Vaadin 14

There is one common issue occurring when we upgrade vaadin 14 to 24

We have multiple custom web components, and one of them is JTJsonTreeView in our multi-module Maven project that is not loading its JavaScript module. The component is defined in a
vaadin-base module and used in a webapp module, but the JavaScript file is never loaded by the browser.

Environment

  • Vaadin Version: 24.7.3
  • Spring Boot Version: 3.5.0
  • Java Version: 24
  • Build Tool: Maven
  • Project Structure: Multi-module Maven project

Project Structure

protocols/
├── vaadin-base/ (library module with shared components)
│ └── src/main/java/…/JTJsonTreeView.java
│ └── src/main/resources/META-INF/resources/frontend/json-tree-view/jt-json-tree-view.js
└── webapp/ (main application module)
└── Uses JTJsonTreeView component

Component Definition (vaadin-base module)

package com.justransform.app.vaadin.components.json.treeview;


  @Tag("jt-json-tree-view")
  @NpmPackage(value = "jsoneditor", version = "9.5.7")
  @NpmPackage(value = "diff", version = "5.0.0")
  @NpmPackage(value = "jsondiffpatch", version = "0.4.1")
  @JsModule("./json-tree-view/jt-json-tree-view.js")
  public class JTJsonTreeView extends Component implements HasSize {
      // Component implementation
  }

Problem

  1. The component is instantiated correctly in Java (constructor is called)
  2. The component is attached to the DOM (visible as element)
  3. However, the JavaScript module jt-json-tree-view.js is never loaded
  4. Browser console shows:
    - No network request for the JS file
    - customElements.get(‘jt-json-tree-view’) returns undefined
    - Component methods (loadContent, etc.) are undefined on the element

What We’ve Tried

  1. Different file locations:
    - vaadin-base/src/main/resources/META-INF/resources/frontend/json-tree-view/jt-json-tree-view.js
    - vaadin-base/frontend/json-tree-view/jt-json-tree-view.js
    - webapp/frontend/json-tree-view/jt-json-tree-view.js
  2. Different JsModule paths:
    - JsModule(“./json-tree-view/jt-json-tree-view.js”)
    - JsModule(“json-tree-view/jt-json-tree-view.js”)
    - JsModule(“/json-tree-view/jt-json-tree-view.js”)
  3. Build commands:
    - mvn clean install
    - mvn vaadin:prepare-frontend
    - mvn vaadin:build-frontend

Expected Behavior

When the JTJsonTreeView component is used in the webapp module, Vaadin should:

  1. Detect the JsModule annotation
  2. Include the JavaScript file in the bundle
  3. Load and execute the JavaScript module
  4. Register the custom element

Actual Behavior

  • The JavaScript file is never requested by the browser
  • No compilation errors during build
  • The component appears in DOM but without any JavaScript functionality
  • Manual dynamic imports also fail with 404 errors

Additional Context

During application startup, we see Lit-related errors for other Vaadin components:
ERROR: No matching export in “node_modules/lit/index.js” for import “adoptStyles”
However, our component doesn’t use Lit - it’s either using LitElement with proper imports or vanilla JavaScript with native Web Components API.

Questions

  1. What is the correct way to structure JavaScript modules for components in a separate Maven module (vaadin-base) that are used in another module (webapp)?
  2. Should the JavaScript files be placed in a specific directory for Vaadin 24 to detect them?
  3. Is there additional configuration needed for multi-module projects?
  4. Why might the JsModule annotation not trigger the loading of the JavaScript file?

Reproduction Steps

  1. Create a multi-module Maven project with vaadin-base and webapp modules
  2. Create a custom component in vaadin-base with @JsModule annotation
  3. Use the component in webapp module
  4. Observe that the JavaScript file is never loaded in the browser

Any guidance on properly configuring custom web components in a multi-module Vaadin 24 project would be greatly appreciated.

Two things immediately come to mind:

  1. ERROR: No matching export in “node_modules/lit/index.js” for import “adoptStyles” might be about some other files but it can also cause some build to be aborted and you will not actually use the JS that Vaadin tried to build. It sounds like the project is using the wrong Lit version.

  2. If you put the JS file in the wrong location, then the build should fail because it does not find the file. Thus it sounds much more like it does not even try to load the file. Why it does not try is hard to know - in development mode it should get all @JsModule annotations from the classpath and include those (only in the production mode build, it tries to figure out what is actually used and needed)

If you create a GitHub or other public project that shows the issue, somebody else can try to see what is wrong.