
The GSAP module was loading twice on half our pages
A small library dependency fix, and how to tell when Drupal is attaching the same asset twice.
The friction
Any page that used a scroll-triggered component and a component with a simple hover
tween loaded gsap.min.js twice: two <script> tags, two separate GSAP instances
registered on window, and the second one silently winning, which meant plugins
registered against the first instance stopped working with no error.
Why
gsap.libraries.yml defined two libraries against the same physical file, for what
seemed like a reasonable reason at the time. A lean gsap/core handled components that only
need basic tweens, and a fuller gsap/scrolltrigger covered anything scroll-driven:
core: js: js/gsap.min.js: {}scrolltrigger: js: js/gsap.min.js: {} js/ScrollTrigger.min.js: {}Drupal’s library system dedupes by machine name and resolves dependencies correctly
within a single library, but core and scrolltrigger are two different libraries that
happen to reference the same file. Nothing about Drupal’s asset system is supposed to
notice that two separately-declared libraries point at identical paths; that’s not a case
it dedupes, because in the general case it isn’t safe to assume it should. A component
depending on gsap/core and another depending on gsap/scrolltrigger on the same page got
gsap.min.js attached twice, once from each library.
The fix
scrolltrigger: dependencies: - gsap/core js: js/gsap.min.js: {} js/ScrollTrigger.min.js: {}scrolltrigger now declares gsap/core as a dependency instead of re-listing the same
file, so Drupal’s own dependency resolution (which does dedupe within a resolved
dependency graph) only ever attaches gsap.min.js once, however many components on the
page ask for it. The obvious fix would have been to merge the two libraries back into one,
but that reintroduces ScrollTrigger.min.js on every page that only needed a basic tween,
which was the entire reason they were split in the first place.
Confirming it
ScrollTrigger.getAll().length before the fix returned inconsistent counts depending on
component order on the page. After the fix, it’s deterministic, and the network panel
shows one request for gsap.min.js regardless of how many components use it.
Improve custom style definition DX using YamlDiscovery is the tracking issue for the broader Canvas/GSAP work this fix shipped alongside.