Problem/Motivation
Olivero ships a preload template with the following:
<link rel="preload" href="{{ olivero_path }}/fonts/metropolis/Metropolis-Regular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ olivero_path }}/fonts/metropolis/Metropolis-SemiBold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ olivero_path }}/fonts/metropolis/Metropolis-Bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ olivero_path }}/fonts/lora/lora-v14-latin-regular.woff2" as="font" type="font/woff2" crossorigin>
This is to support fonts.css which is loaded as part of the global-styling library.
Steps to reproduce
With Umami, check the network tab in devtools, and see that the fonts are loaded at the same time or before the CSS, instead of only after the CSS is loaded.

Proposed resolution
Add a 'fonts' key to libraries.yml and then process this in HtmlResponseAttachmentsProcessor, with initial support for preload.
Convert Olivero to use it.
e.g.
global-styling:
version: VERSION
fonts:
fonts/metropolis/Metropolis-Regular.woff2:
preload: true
This will add an html link tag with rel=preload pointing to the font.
In #3570909: Support early hints for fonts we can add support for early hints .
Remaining tasks
Once this is in, we can use the new API to add support for early hints too #3563782: [PP-1] Use early hints for CSS
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #41 | Screenshot from 2026-04-20 08-35-09.png | 141.63 KB | catch |
| #25 | Screenshot from 2026-02-01 17-48-35.png | 136.63 KB | catch |
| #25 | Screenshot from 2026-02-01 17-47-57.png | 162.57 KB | catch |
Issue fork drupal-3366561
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3366561-support-preload
changes, plain diff MR !14586
- 3366561-11.x
changes, plain diff MR !15546
Comments
Comment #2
catchComment #3
vbouchetI understand that for now, given the example, it is to add the possibility to specify additional "things" with the library that would generate the link tags. What about the existing external / js that are added in a library?
Should we do something like:
or
The second option allows a lot of flexibility (and cover the example of fonts) but is much more verbose.
Third option is a mix, allowing for shorter version for elements of the library (like example 1) and verbose version for other elements.
I am curious of a direction as we are for now implementing custom on a project but would be keen to write a patch for this to land in core the proper way.
Comment #4
catchI kind of like the more verbose option even for the same file, because you could have two files from the same CDN and then defining prefetch inline for one file (or both) doesn't seem ideal. We could always add a shorthand in a follow-up.
Comment #5
rikki_iki commented@catch thanks for the redirect to this issue. As I posted on the other issue, in my mind I think a definition like this would be nice;
dns-prefetch would also have it's own entry. I think having separate entries instead of one generic 'links' entry reduces the risk of user error (and general misuse - eg putting css and js into the links entry). It's also clearer to read.
Comment #6
catchThat looks pretty nice to me as an API. We'd have to handle any additions/removals manually but maybe that is fine.
Comment #7
macsim commentedAhem, since the other issue was opened in 2022 and this one in 2023, the duplicate is this one, not the former...
We should have close that issue and improve the original.
Comment #8
rikki_iki commentedThe other issue has been postponed for a year, and no one seemed to care... I don't mind which issue so long as it stays active.
DNS prefetch is more widely supported and recommended as a fallback for Preconnect (see support), so maybe we can build that in? Or instead of two separate entries it's something like;
To optionally add a preconnect hint for certain dns-prefetch items, since preconnect usage should be limited to only critical assets;
Regarding preload, there's also modulepreload to consider. I don't know if we want to have yet another entry just for this separate rel value or if we could so something like;
And if the preload has
type:modulewe can swap the rel value over? Or justas:module?And then how should we handle the
crossoriginattribute? Currently it can be added via attributes which I guess is fine.Comment #9
macsim commentedI don't really mind as well it's just about people who spent hours thinking about the problem / trying to fix it / reviewing code / rerolling it and who will never get credit for that.
As long as the subject moves forward it's good, so now that it's been done, let's continue here.
Comment #10
catch@macsim we can transfer issue credits over, but I'm not sure which issue you're talking about to be honest, there are at least three somewhat related to this one with different approaches. If you link it, I'll look at transferring relevant credits over.
Comment #11
rajab natshahIt would be so nice if we could manage preloading from libraries directly.
(Interaction Observer IO API and Preloading API) in Drupal Core
Comment #12
catchWe can probably add early hint support on top of this too #3563782: [PP-1] Use early hints for CSS.
Comment #13
catchAlternative approach for fonts at #3565331: Allow themes to inline font declarations.
Comment #14
catchThought about this a bit more.
I agree with @rikki_iki's comment in #5:
It's possible to add all of these things with #attached['html_head_link'] and #attached['http_header'] in hook_preprocess_page() so there's already a way for themes to do this in PHP. What we're looking for here is a more convenient/structured way to do font preloading since it's the common use-case.
Given that, for fonts I think we should do something like this:
As a top level item alongside CSS. We'd then need to add support for this into the asset resolver and collect these in
HtmlResponseAttachmentsProcessorIf a font is listed without anything extra set, then nothing happens, but it allows the theme to be explicit about that.
For module preloading maybe we can do something like this - put the preload hint directly on the definition of the file:
To make progress here, I'd prefer to open separate issues to look at generic preconnect support for third party domains and also js module preloading, these will need different treatment and a different API.
Comment #15
berdirNot caught up, just one note on fonts.
We added something like this (just preload, not early hints) to https://drupal.org/project/bs_base, by adding preload fonts to theme.info.yml. One tedious bit was cache busting, we for example have an icon font that updates pretty frequently and because this isn't the canonical font definition (that's in CSS), it's very easy for the actual font-face in CSS and this preload info to get out of sync, resulting in loading two different files. That doesn't just defeat the whole purpose, it makes it worse than not having it at all.
I'm not sure what a good solution for this is to be honest, in our case we then added support for updating the .info.yml definition into the icon font build toolchain. I think if core respects the library version and adds that to the URL, similar to CSS/JS assets then that's probably OK and we could update our toolchain to maintain the library version for us?
Comment #16
catch@berdir I don't think we can do that because if we add the version string in the preload link, that URL will be different to the one in the CSS file unless they're manually kept in sync, so would lead to two http requests.
Cache busting isn't made worse by this though.
Comment #17
berdirYes, that's my point. The two URL's must be the same, the CSS URL would need to use the same version string. I guess if the following definition works then that's also OK?
I'm just saying that this is something that you need to keep in mind, it must be the exact same URL, and if you have it in two different places, it's easy to forget to update them if it's not automated.
Comment #18
catchYes manually adding the version string in a query parameter in both places would work fine.
Comment #20
catchHere's a start. Replaces Olivero's preload template as a proof of concept.
Tried to require the absolute minimum amount of information in libraries.yml so we're not rebuilding the html_head_link API in YAML.
We can add 103 early hints support on top of this without a lot of work. Probably simpler to do that in a follow-up issue to this one.
@todos here:
1. We can add support to Umami and Navigation
2. Explicit test coverage
But would be nice to get a review of the API/implementation in the meantime.
Comment #23
finnsky commented1. Fixed phpcs
2. Added support for Navigation
---
We need to fix path resolving
http://localhost:8888/node/add/core/modules/navigation/assets/fonts/inte...
on inner pages it is wrong.
Comment #24
catchPushed a fix to use file_url_generator. This required updating some unit tests but pipeline appears to have got past those.
Also implemented the API in Umami for the fonts that are loaded on a front page request. Because Umami doesn't do any preloading at all at the moment this should be visible on https://gander.tag1.io/ (after commit) and possible to before/after in lighthouse locally.
Comment #25
catchLighthouse before and after just to show it working in Umami.
Comment #26
catchThere's existing NightWatch test coverage for Olivero font preloading.
Added unit test coverage for AssetResolver.
Also added an additional assertion to the performance test in Navigation module.
Comment #27
catchOpened #3570909: Support early hints for fonts for early hints. Should be clean to add on top of this one, but better to keep this reviewable.
Comment #28
smustgrave commentedThis one needs a rebase, but based on lauriii comment should a CR be added? Or IS updated?
Comment #29
catchExpanded the proposed resolution in the issue summary.
Yes we should add a change record here but I'd prefer to do that once the API has had more review.
Comment #30
catchComment #31
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. The merge request has merge conflicts and cannot be merged. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #32
catchRebased.
Comment #33
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #34
catchRebased.
Comment #35
grimreaperHello everyone,
Thanks all for the discussions and work on this issue!
This looks promising!
I put some review comments on the MR.
Comment #36
catchFixed or replied to all the review points I think (including one test change I initially didn't want to do but have now done and it's better).
Comment #37
catchLatest changes broke performance tests, but in a good way - because we filter libraries by asset type,and the libraries with fonts are more stable across pages than the libraries with CSS (because there's less of them), the cache hit rate on the asset resolver cache entry is a lot higher.
Comment #38
grimreaperThanks @catch for pushing this.
I change to needs work as last pipeline failed.
Otherwise RTBC for me.
Comment #39
catchUpdated that test, missed it in the previous round of changes. Also added a change record now there's a bit more consensus on the API.
#3570909: Support early hints for fonts should be doable as soon as this lands.
Comment #40
grimreaperThanks.
I gave a last quick review.
Comment #41
catchUploading a screenshot of chromium devtools network tab showing the fonts loading just before the CSS in Umami, whereas in HEAD they would load only after the CSS is loaded and parsed. Olivero there will be no change because it already implements preloading, it's just able to switch to the new API.
I'll open an issue for default_admin to use the new API too.
Comment #42
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #43
catchRebased - just performance tests to update.
Comment #44
grimreaperI thought about something.
I need to check about the library declaration in SDC, if there is an impact and if possible to have a component declared library to provide fonts too.
I will try to do that today.
Comment #45
grimreaperComment #46
grimreaperLike in comment #3565258-67: Support library-specific aggregates and next comments, should we handle fonts from component libraries in a follow-up issue?
Comment #47
catchMaybe one follow-up issue to respect additional library definition keys in components.yml? It's possible that it also works by accident but even if it does would be good to add test coverage and documentation.
Comment #48
grimreaperFollow-up issue created #3586470: Support preloading of fonts declared from components.
Back to RTBC :)
Comment #51
alexpottCommitted 1c65c7a and pushed to main. Thanks!
Committed ac409b9 and pushed to 11.x. Thanks!
Comment #56
alexpottBah - this was wrong to try to resolve merge conflicts on the fly... ho hum. reverted from 11.x... will open an MR against 11.x
Comment #58
alexpottCommitted 26b9607 and pushed to 11.x. Thanks!
Comment #63
grimreaperFollow up issue #3586470: Support preloading of fonts declared from components to add this feature in SDC ready for review.