-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webfonts API: Output only used fonts #39099
Conversation
58ed84d
to
afe1b56
Compare
5582859
to
64c912f
Compare
8825187
to
6a5d8ae
Compare
@justintadlock I'm going the filter route in this PR. I'm thinking of creating an issue regarding exposing the |
b3ce575
to
23a8205
Compare
23a8205
to
a0e8182
Compare
@zaguiini I think that should work. There are probably some other cases with supporting non-block content, such as plain HTML elements from classic posts. But, again, out of scope. WP really needs to allow theme devs to style all HTML elements via |
return $response; | ||
} | ||
|
||
$this->invalidate_globally_used_webfonts_cache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unnecessary. Solely updating the option as I'm doing in the next line is enough.
public function register_current_template_filter() { | ||
$templates = get_block_templates( array(), 'wp_template' ); | ||
|
||
foreach ( $templates as $template ) { | ||
add_filter( | ||
$template->slug . '_template', | ||
function() use ( $template ) { | ||
$this->register_used_webfonts_by_template( $template ); | ||
} | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@creativecoder Do you happen to know if there's a single hook that returns the current template instead of what we're doing here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The $template_html
global is available in wp_head
, and contains all the HTML of the page if that helps (in block themes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it contain the slug too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it contain the slug too?
No, $template_html
is set in the template-canvas.php
file when building the page, and only contains the HTML for the page:
$template_html = gutenberg_get_the_template_html(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, so it won't really work for our use case since we need the slug too.
… used in the front-end
… all the webfonts used in the front-end
a0e8182
to
3fcd821
Compare
3fcd821
to
62d677b
Compare
This is a really important step forward for the Webfonts API, thank you for tackling it, @zaguiini ! While this change largely works for removing unused font-face declarations, a couple things worry me about the approach. The first is that the initial Webfont API we have now can be used in many different (and possibly unexpected) ways that might feel broken if we filter out fonts by default (unless they are used in a very specific way). For example, any css files included in a theme, or custom css from a plugin that registers a specific font would not be detected here, the font-face rule removed, and the font not loaded. It seems like it would be better if the Webfonts API had an explicit way to differentiate between
My second concern is the complexity of caching what fonts are used for what templates when they are saved. This seems like it might be fragile if something unexpected happens between saving and outputting the templates, and that it would be better to check what fonts are used as the page is loaded, if at all possible. Since I anticipate continuing to iterate on this approach, I created #39332 as a hub for discussing and tracking work on this area. |
We're closing this PR since it's not going to be merged because of the implementation. However, as pointed above, there's an issue for it now: #39332. |
What
In #37140, we finally introduced the Webfonts API. The initial implementation has a pitfall: it includes every registered font, even if it's not being used, to the output.
This PR addresses exactly that: it introduces a mechanism to remove webfonts that are not used by the providers when emitting inline CSS that's sent to the front-end.
Why
A single
@font-face
declaration could add up to 2kb to every request. Imagine someone registering 100 fonts to a provider so one single font could be picked up in FSE. Without this filtering mechanism, we'd add a lot of useless information per request. It can -- and probably will -- become a problem very quickly.How
I'm looking up the contents of the current template for every request and saving its used webfonts as an option. This happens for every template, lazily.
Fonts used in the global styles settings are also cached. We're caching because this is an expensive operation.
The cache is invalidated on every update of:
And also when the current theme changes.
The content (post/page content) is also processed, per request, to include webfonts used by the blocks inside the current post or page. There is no cache for this type of content, but there might be if someone requests it.
It also includes a filter called
gutenberg_used_webfonts
so one can override the decision of the mechanism, either by adding or removing fonts as needed. This is a concern raised by @justintadlock regarding a few blocks that do not have the font-family attribute yet. It's a workaround until all blocks get the possibility to change the font family inside the block editor instead of working around it by using additional CSS classes.Testing
You should check only the used fonts are included as inline CSS when the webfont is picked as:
TODO