Skip to content

feat: deprecate @JsModule with a runtime URL and skip it from the bundle - #24654

Draft
Artur- wants to merge 16 commits into
javascript-is-runtimefrom
jsmodule-is-bundle
Draft

Artur- wants to merge 16 commits into
javascript-is-runtimefrom
jsmodule-is-bundle

Conversation

@Artur-

@Artur- Artur- commented Jun 16, 2026 •

Copy link
Copy Markdown
Member

Stacked on #24653 — review/merge that first; this PR's base is javascript-is-runtime.

@jsmodule is for build-time bundle sources only. A @jsmodule value with a runtime URL prefix (context://, base://, /abs, http(s)://, //) keeps loading at runtime as a <script type="module"> (via Page.addJavaScript(url, LoadMode.EAGER, JavaScript.Type.MODULE)), but is now filtered out of the bundle imports and triggers a build-time deprecation warning.

  • The bytecode scanner (FrontendClassVisitor) tracks such values on ClassInfo.deprecatedRuntimeModules instead of adding them to the bundle imports, and the full-classpath scanner (FullDependenciesScanner, used in development mode by default) skips them as well.
  • FrontendDependencies emits one consolidated build-time warning per scan listing every such (class, value) usage, recommending migration to @javascript(value=..., type=Type.MODULE) for runtime <script type="module"> loading.
  • UIInternals loads runtime-URL @jsmodule values at runtime and no longer reports them as missing from the production bundle.
  • The @JsModule Javadoc documents the deprecation and points to @JavaScript(type = Type.MODULE).

@jsmodule is for build-time bundle sources only. A @jsmodule value with a
runtime URL prefix (context://, base://, /abs, http(s)://, //) keeps
working at runtime via Page.addJsModule, but is now filtered out of the
bundle imports and triggers a build-time deprecation warning.

- The scanner (FrontendClassVisitor) tracks such values on
  ClassInfo.deprecatedRuntimeModules instead of adding them to the bundle
  imports.
- FrontendDependencies emits a one-time consolidated build-time warning
  per (class, value) recommending migration to
  @javascript(value=..., type=Type.MODULE) for runtime
  <script type="module"> loading.

This removes the previous double-load where an external @jsmodule URL was
both bundled and loaded at runtime.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@github-actions

github-actions Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

 1 667 files  ±0   1 753 suites  ±0   2h 6m 44s ⏱️ - 7m 54s
12 961 tests +6  12 892 ✅ +6  69 💤 ±0  0 ❌ ±0 
13 595 runs  +6  13 526 ✅ +6  69 💤 ±0  0 ❌ ±0 

Results for commit 6d1664a. ± Comparison against base commit db0b9eb.

♻️ This comment has been updated with latest results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added +0.0.1 and removed +0.1.0 labels Oct 19, 2026
totally-not-ai Bot and others added 3 commits October 19, 2026 07:04
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… checks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@totally-not-ai

Copy link
Copy Markdown
Contributor

Fixed the three SonarCloud issues: the two lambdas in UIInternals.warnForUnavailableBundledDependencies are now JavaScript::value and JsModule::value, and FrontendDependencyUrlResolver.isRuntimeDependencyUrl now lowercases with Locale.ROOT, so the prefix match doesn't depend on the default locale (e.g. the Turkish dotless i).

# Conflicts:
#	flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendDependenciesTest.java
@Artur-

Artur- commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

If this depends on another PR, let's stack it on top of that/those

totally-not-ai Bot and others added 3 commits October 19, 2026 12:52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dule-is-bundle

# Conflicts:
#	flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/scanner/FrontendDependencies.java
#	flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendDependenciesTest.java
#	flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RuntimeJavaScriptComponent.java
#	flow-server/src/test/java/com/vaadin/flow/component/internal/RuntimeJavaScriptDependencyTest.java
#	flow-server/src/test/java/com/vaadin/flow/server/FrontendDependencyUrlResolverTest.java
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@totally-not-ai
totally-not-ai Bot changed the base branch from main to javascript-is-runtime October 19, 2026 12:56
totally-not-ai Bot and others added 3 commits October 19, 2026 13:07
The full-classpath scanner, used in development mode by default, only
skipped runtime-prefixed @javascript values, so a @jsmodule with a runtime
URL was still bundled there while also being loaded at runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…deprecation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@totally-not-ai

Copy link
Copy Markdown
Contributor

@Artur- Done — this PR is now stacked on #24653: the base is javascript-is-runtime, and that branch is merged in, so the diff only shows the @JsModule changes. While resolving the merge I folded the runtime-URL @JsModule warning into the same consolidated, once-per-scan style #24653 uses for bundled @JavaScript, with a test for it. I also replaced #24653's jsModuleWithRuntimePrefix_stillBundled with jsModuleWithRuntimeUrl_excludedFromBundleImports, since excluding those values from the bundle is the point of this PR.

totally-not-ai Bot and others added 3 commits October 20, 2026 10:22
…dule-is-bundle

# Conflicts:
#	flow-server/src/main/java/com/vaadin/flow/component/internal/UIInternals.java
#	flow-server/src/test/java/com/vaadin/flow/component/internal/RuntimeJavaScriptDependencyTest.java
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dule-is-bundle

# Conflicts:
#	flow-server/src/test/java/com/vaadin/flow/component/internal/RuntimeJavaScriptDependencyTest.java
@totally-not-ai

Copy link
Copy Markdown
Contributor

Merged javascript-is-runtime (69eabc8). One conflict needed a decision: the base branch added absoluteJsModule_notAddedAtRuntime and a comment stating that a / @JsModule is bundled and not loaded at runtime. This PR deliberately treats / as a runtime URL for @JsModule (left out of the bundle, loaded at runtime, deprecation warning), so I kept this PR's behaviour, dropped that test (/abs/module.js is covered by the parameterized runtime-URL test instead), and reworded the comment in UIInternals to point at the scanner-side runtime URL check. The base's externalScript/absoluteScript tests were already covered by the same parameterized test.

A @jsmodule value only reaches this point when it already has a runtime
URL prefix, which resolveToContextRoot returns unchanged, so it can
never resolve to null.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant