Skip to content

Performance

When to Use

  • You're optimizing component loading
  • You're debugging slow page loads with many components
  • You're implementing caching strategies

Decision

Pattern: Automatic Library Loading

Components automatically generate asset libraries, loaded only when component renders.

Generated Library Format: - core/components.{provider}--{component-name} - Includes matching .css and .js files - Auto-attached when component renders - Aggregated with other libraries in production

WHY automatic is better: No manual library management. Assets only load when component actually used on page.

Pattern

Pattern: Library Dependencies

Declare dependencies to optimize loading order. libraryOverrides is the only key core reads — there is no libraryDependencies (see Component YAML Schema).

libraryOverrides:
  dependencies:
    - core/once          # core/drupal is appended automatically
  js:
    my-component.js:
      attributes: { defer: true }  # Non-blocking load
      preprocess: true             # Enable aggregation

The js: key here replaces the auto-discovered my-component.js entry rather than adding to it (array_merge at ComponentPluginManager.php:213-216), so list the file with the same name you want to keep loading.

Pattern: Render Caching

Cache component render output when possible.

// In render array
$build = [
  '#type' => 'component',
  '#component' => 'my_theme:card',
  '#props' => [...],
  '#cache' => [
    'keys' => ['card', $node->id()],
    'contexts' => ['user.permissions'],
    'tags' => $node->getCacheTags(),
    'max-age' => 3600,
  ],
];

Pattern: Lazy Loading Components

For below-fold or modal components, consider lazy loading.

{# Use BigPipe for heavy components #}
{{ attach_library('core/drupal.ajax') }}

<div
  data-big-pipe-placeholder-id="..."
  data-drupal-ajax-processor="big_pipe"
>
  {# Heavy component loads async #}
  {{ include('my_theme:heavy-component', {...}) }}
</div>

Pattern: CSS Performance

Minimize component CSS file size and complexity.

/* ✓ GOOD: Simple, scoped selectors */
.my-component { }
.my-component__element { }
.my-component--variant { }

/* ✗ BAD: Deep nesting, complex selectors */
.my-component .wrapper .inner .element .child { }
.my-component:not(.variant):not(.disabled) > * + * { }

Common Mistakes

Common Mistake: Including heavy JavaScript libraries in every component. WHY: Bloats page weight. Use libraryOverrides: dependencies: to share one common library across components rather than duplicating code per component.

Common Mistake: Not enabling CSS/JS aggregation in production. WHY: Individual component files create many HTTP requests. Enable aggregation in production settings.

Common Mistake: Over-componentizing (components for every small element). WHY: Each component has overhead. Group related elements together when they always appear together.

See Also