Skip to content

build: decouple JS API client bundling into an optional module#4603

Open
dsmiley wants to merge 1 commit into
apache:mainfrom
dsmiley:build_jsClientOptional
Open

build: decouple JS API client bundling into an optional module#4603
dsmiley wants to merge 1 commit into
apache:mainfrom
dsmiley:build_jsClientOptional

Conversation

@dsmiley

@dsmiley dsmiley commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

(AI gen, human reviewed)
The OpenAPI-generated JS client (npm install + babel build + browserify bundle) was embedded directly in :solr:webapp's build.gradle, making that module quietly depend on npm/node for something unrelated to compiling/packaging the webapp itself. Pull it out into its own module, :solr:webapp:js-client, which exposes the built bundle via a jsClientBundle configuration that :solr:webapp now consumes as a normal cross-project dependency (mirroring how it already consumes :solr:server's serverLib/solrCore and :solr:api's jsClient outputs), instead of :solr:webapp defining the npm tasks and reaching into its own local task outputs.

The new module is written in Kotlin DSL (build.gradle.kts) rather than Groovy, because Kotlin DSL's static typing advantages. It avoided a bug or two!

Also make the JS client bundle optional, mirroring the existing disableUiModule pattern:

  • settings.gradle: new -PdisableJsClient=true flag (gradle.ext.withJsClient), excluding :solr:webapp:js-client from the build entirely when set.
  • solr/webapp/build.gradle: the generatedJSClientBundle dependency is only added when the flag is on; the war{} block's from(configurations.generatedJSClientBundle) is left unconditional since an empty configuration is already a safe no-op.
  • build.gradle: mirrors gradle.ext.withJsClient into rootProject.ext, matching the existing withUiModule convention.

Refactor gradle/node.gradle so it no longer hardcodes which projects need node/npm. Previously it named :solr:solr-ref-guide and :solr:webapp explicitly; now those projects apply the node-gradle plugin themselves in their own build.gradle(.kts), and gradle/node.gradle just reacts via allprojects { pluginManager.withPlugin(...) { ... } } to configure whichever projects end up applying it (proxy/registry override, pinned node version, .gradle/node workdir layout). This makes "does this module need node?" answerable by reading the module's own build file instead of a central list, and removes the maintenance burden of keeping that list in sync.

Verified end-to-end: default build (:solr:webapp:war) produces an identical war to before (same libs/solr/{README.md,docs/,index.js} contents); with -PdisableJsClient=true the war omits libs/solr entirely and zero npm/node tasks run; :solr:solr-ref-guide still exposes its node/npm tasks after self-applying the plugin.

The OpenAPI-generated JS client (npm install + babel build + browserify bundle)
was embedded directly in :solr:webapp's build.gradle, making that module quietly
depend on npm/node for something unrelated to compiling/packaging the webapp
itself. Pull it out into its own module, :solr:webapp:js-client, which exposes
the built bundle via a `jsClientBundle` configuration that :solr:webapp now
consumes as a normal cross-project dependency (mirroring how it already consumes
:solr:server's serverLib/solrCore and :solr:api's jsClient outputs), instead of
:solr:webapp defining the npm tasks and reaching into its own local task outputs.

The new module is written in Kotlin DSL (build.gradle.kts) rather than Groovy,
because Kotlin DSL's static typing advantages.  It avoided a bug or two!

Also make the JS client bundle optional, mirroring the existing disableUiModule
pattern:
- settings.gradle: new -PdisableJsClient=true flag (gradle.ext.withJsClient),
  excluding :solr:webapp:js-client from the build entirely when set.
- solr/webapp/build.gradle: the generatedJSClientBundle dependency is only added
  when the flag is on; the war{} block's from(configurations.generatedJSClientBundle)
  is left unconditional since an empty configuration is already a safe no-op.
- build.gradle: mirrors gradle.ext.withJsClient into rootProject.ext, matching
  the existing withUiModule convention.

Refactor gradle/node.gradle so it no longer hardcodes which projects need
node/npm. Previously it named :solr:solr-ref-guide and :solr:webapp explicitly;
now those projects apply the node-gradle plugin themselves in their own
build.gradle(.kts), and gradle/node.gradle just reacts via
`allprojects { pluginManager.withPlugin(...) { ... } }` to configure whichever
projects end up applying it (proxy/registry override, pinned node version,
.gradle/node workdir layout). This makes "does this module need node?"
answerable by reading the module's own build file instead of a central list,
and removes the maintenance burden of keeping that list in sync.

Verified end-to-end: default build (`:solr:webapp:war`) produces an identical
war to before (same libs/solr/{README.md,docs/,index.js} contents); with
-PdisableJsClient=true the war omits libs/solr entirely and zero npm/node tasks
run; :solr:solr-ref-guide still exposes its node/npm tasks after self-applying
the plugin.
@dsmiley dsmiley requested a review from gerlowskija July 2, 2026 18:14
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Dependency upgrades tool:build admin-ui labels Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

admin-ui dependencies Dependency upgrades documentation Improvements or additions to documentation tool:build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant