Defining Efficient Libraries: Minimal .libraries.yml in Drupalfor Drupal 11 , 10 , 9 , and 8

Last updated :  

Picture a delivery truck that drops off every package on its route to every house, whether that house ordered anything or not. That's what a bloated Drupal library does to every page load: it ships jQuery, three unrelated widgets, and a stylesheet nobody asked for, just because they all live in the same file. A well-defined .libraries.yml library is the opposite — a precisely addressed parcel, sent only to the page that actually needs it.

What you'll learn in this lesson

  • How Drupal's .libraries.yml file groups CSS/JS into named, independently-loadable bundles
  • Why splitting one big library into several small ones reduces wasted bytes on every page
  • How dependencies let one library pull in exactly what it needs — nothing more
  • How version feeds into asset-hash generation, and why forgetting to bump it causes stale-cache bugs

A real library definition, line by line

Here's a genuine .libraries.yml file from Drupal's own Examples module, defining two separate libraries:

accordion:
  # Starting from Drupal 10.1.2, the version information plays a critical role
  # in generating a unique hash for aggregated files. It is important to update
  # the version value whenever a referenced file undergoes changes.
  version: 4.0.0
  js:
    js/accordion.js: {}
  css:
    component:
      css/accordion.css: {}

colors:
  version: 4.0.0
  css:
    component:
      css/weights.css: {}
  js:
    # We use weight as example attribute. Its usage is discouraged, though;
    # dependencies should instead be used.
    js/colors.rgb.js: { weight: -2 }
    js/colors.base.js: { weight: -8 }
    js/colors.cmy.js: { weight: -4 }
  dependencies:
    - core/jquery
    - core/drupalSettings

Two libraries, not one

Notice this file defines accordion and colors as two completely separate top-level keys — two independent libraries a page can attach individually. A page that only needs the accordion widget never loads the color-picker JavaScript, and vice versa. This is the single biggest lever in "minimal libraries": don't bundle unrelated functionality into one library just because it's convenient to write once. Every unattached-but-still-loaded byte is pure waste.

css.component vs. a bare css key

CSS assets are grouped by SMACSS category — base, layout, component, state, or theme. Using component here tells Drupal's aggregator this stylesheet styles a specific, self-contained widget (the accordion), which affects load order relative to other categories. Getting the category right isn't cosmetic — it's part of how Drupal decides what can safely be aggregated together.

dependencies: pull in only what you need

dependencies:
  - core/jquery
  - core/drupalSettings

The colors library declares its own dependencies explicitly rather than assuming jQuery is "probably already loaded somewhere." This is the correct pattern: Drupal resolves the dependency graph and loads core/jquery exactly once, however many libraries depend on it — you never need to (and shouldn't) list a dependency's own dependencies again.

The weight gotcha: the comment in the real file above is not decoration — it's a warning from the Examples module's own authors. Using weight to force load order (as `colors` does for its three JS files) is fragile and discouraged for anything beyond same-library file ordering. If library B genuinely needs library A to load first, express that with dependencies, not a weight number you have to keep synchronized by hand.

Why version isn't optional

Since Drupal 10.1.2, version feeds directly into the hash Drupal generates for aggregated file URLs. Change a file's contents but forget to bump version, and visitors with a cached copy of the old aggregate may keep serving stale CSS/JS indefinitely — a genuinely confusing bug to track down, since the deployed code is correct and the browser cache is "wrong" for a reason nobody can see. Bump the version number every time you meaningfully change a library's files.

Quick check: you have a library used by exactly one page on a low-traffic admin screen, bundled together with a library used on every single front-end page. What's the actual performance cost of leaving them combined? (If you said "every front-end visitor downloads code for a screen they'll never see," you've got the core idea — the fix is splitting them into two separate library keys, exactly like accordion and colors above.)

Key takeaways

  • Each top-level key in a .libraries.yml file is an independently attachable library — split unrelated functionality into separate libraries rather than bundling it into one.
  • Use dependencies to pull in another library's assets; never hand-list a dependency's own dependencies.
  • CSS files are grouped by SMACSS category (base/layout/component/state/theme) — pick the category that matches what the CSS actually does.
  • Avoid weight for ordering between libraries; reach for dependencies instead. Weight is only reasonable for ordering files within the same library.
  • Bump version whenever a library's files change — Drupal 10.1.2+ uses it to generate the aggregation hash, and forgetting causes silent stale-cache bugs.

Coming up next

Defining a lean library is only half the job — the next lesson covers the other half: attaching it conditionally, so even a perfectly minimal library only loads on the pages that actually need it.