feat: lazy useDrupalCe().loadLibrary() for on-demand Drupal JS libraries#504
Merged
Conversation
…braries
Expose a loadLibrary() API so custom components can lazily load a Drupal
library (form #states, autocomplete, …) exactly when needed. The loader —
ordered script queue, dedup, drupalSettings seeding, run-once attachBehaviors
— lives in its own module (drupalLibraryLoader) reached via a dynamic import(),
so it and the Drupal JS it pulls in are split into a separate chunk fetched
only on first use, not shipped in the main bundle.
Accepts a resolved library ({ js, drupalSettings }, as emitted on a
<drupal-library-*> element) or a library name resolved via a companion
/drupal-library/{name} backend endpoint.
fago
approved these changes
Jul 6, 2026
added 3 commits
July 6, 2026 11:22
Cache the dynamic import() of the loader in one module-level promise so all loadLibrary() callers await the same promise; their continuations then run in strict call order, keeping libraries enqueued in dependency order even when many <drupal-library-*> elements call it in the same tick (per-call import() can resolve out of order under Vite dev, scrambling the load order).
The backend emits each library's resolved JS (and merged drupalSettings) on the
<drupal-library-*> element, so loadLibrary() just loads that — drop the
by-name variant and the /drupal-library/{name} fetch.
Unit-test drupalLibraryLoader: ordered/absolute script injection, async=false tagging, dedup across calls, dependency order across calls, and drupalSettings seeding (with a mocked script insertion that loads immediately).
fago
approved these changes
Jul 6, 2026
fago
approved these changes
Jul 6, 2026
Ship the renderless drupal-library--default scaffold component (a thin consumer of loadLibrary()) alongside the other drupal-* defaults, and cover it: renders no markup and loads the resolved library on mount.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Expose a
useDrupalCe().loadLibrary()API so a component can lazily load a Drupal JS library (form#states, autocomplete, …).Design
The heavy loader — ordered script queue + dedup,
drupalSettingsseeding, run-onceDrupal.attachBehaviors()— lives in its own module (drupalLibraryLoader.ts) reached via a dynamicimport()from the composable, so the loader and the Drupal JS it pulls in are split into a separate chunk fetched only on firstloadLibrary()call — nothing ships in the main bundle for pages that never touch a Drupal library.loadLibrary(library)takes the backend-resolved library{ js, drupalSettings }— the shape the backend emits (JS files in dependency order + merged settings) on a<drupal-library-*>custom element. The frontend just loads it; there is no name→assets resolution on the client. Server-side it's a no-op.The loader
import()is cached in a single module-level promise so all callers await the same promise and enqueue in strict call order — otherwise per-callimport()can resolve out of order (Vite dev) and scramble the load order.Context
Foundation for decoupled webform conditions — drunomics YouTrack MCD-605 / MCD-607. The backend that generates the
<drupal-library-*>elements lives in the custom_elements module (drupal.org MR pending).Drafted with Claude Code from the loki dev VM.