Directory

Webfonts: scan content for webfonts and enqueue them by zaguiini · Pull Request #39399 · WordPress/gutenberg · GitHub
Skip to content
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: scan content for webfonts and enqueue them #39399

Conversation

zaguiini
Copy link
Contributor

@zaguiini zaguiini commented Mar 11, 2022

We've since created an alternative approach that we find preferable to this PR. It can be found here. #39559

Part of #39332. Read #39332 (comment) to gather more context about the whole picture regarding the implementation.

What?

Now that we are not outputting all the registered fonts (#39327), we need to scan the content for actually used fonts and enqueue them. We are placing filters for content, global styles, and templates so we can crawl for webfonts and enqueue them. We are scanning all the post types that stock WordPress exposes through its API.

Why?

Performance. #39332 has more about it.

How?

We're hooking into every possible post type and enqueueing the webfonts that they are using. The webfonts found are then put in a cache (which is wiped on save) so it doesn't slow down the rendering process.

The process is a little different for templates and template parts since they might or might not be a post entry: if the template is pristine, there's no post, and the template is read from disk. That's why we cannot use meta attributes for them. Instead, they use a theme mod so the cache is wiped when the theme is switched.

Testing Instructions

  1. Follow the steps on Webfonts API: expose enqueueing method instead of directly enqueueing fonts on registration #39327 to register a webfont;
  2. Open the block editor and include a block which allows typography customization;
  3. Pick the registered webfont and save the content.

Refresh the page and you should see the custom webfont there. It also works for global styles.

TODO

  • Tests.

* that has been loaded in the front-end.
*/
public function register_filter_for_current_template_webfonts_enqueuing() {
$template_type_slugs = array_keys( get_default_block_template_types() );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this work for custom templates?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will only work for custom templates with the same slugs as those defaults, but I think would miss others that could be created by users or developers (like header-footer-only for example isnt part of the default list.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if gutenberg_get_block_templates would work to create a slug list like this from? I think that should be retrieving all templates both from the theme file structure and the database.

Copy link
Contributor Author

@zaguiini zaguiini Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if I got this right, get_default_block_template_types returns a list of the "slots" where the templates are applied. If this is right, then I think we should be good to go -- we want to hook into the rendered templates and scan them for fonts as lazily as possible.

Copy link
Contributor Author

@zaguiini zaguiini Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gutenberg_get_block_templates retrieves all templates, whether they're rendered or not, and that might be costly because "existing" doesn't mean that the template is actually being used. I think a good idea would be to be as lazy as possible and only cache the fonts for the templates are actively on the page.

/**
* Set up the actions to invalidate webfont cache.
*/
private function register_webfont_cache_invalidation_actions() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function, I thought of two approaches:

  1. Hook into save_post and get the $post->post_type to determine the invalidation method (theme mod or meta attribute);
  2. The one I picked. I feel it's easier to understand and it looks to fit more the WP filter/action definitions.

@zaguiini
Copy link
Contributor Author

Test failures are not related to the changes proposed by the PR. End to End Tests are failing regularly on trunk.

@jeyip jeyip force-pushed the try/expose-enqueue-webfont-method branch 3 times, most recently from c9ca5cf to fc3c8e9 Compare March 14, 2022 21:45
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from 18819cd to f66950b Compare March 15, 2022 17:35
@zaguiini zaguiini force-pushed the try/expose-enqueue-webfont-method branch from be66425 to 7b4900a Compare March 15, 2022 17:44
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from f66950b to 9440eba Compare March 15, 2022 17:48
@aristath
Copy link
Member

I just wanted to add something to the conversation here:
I got a message/question on Slack a couple of days ago, about whether or not the webfonts API can be used to add a webfont used in a cookie banner.
Granted, a "cookie banner" is not something that would necessarily need a custom webfont, however, it got me thinking about JS-injected content.
There are tons of implementations and ways to build themes, render content etc. If we scan the content to get the font-families used in the content that is available on-render, then any content that gets injected via JS won't be parsed and we won't be able to check that for webfonts availability.
Another example: A few years ago I built a theme which was only rendering the header & main-content on initial page-load. The sidebars and footer were fetched after the initial page-load via AJAX, making the initial page-load faster. The logic was that when you visit a page you start from the top, and if the footer takes an extra second to load there's no harm 'cause it will take the visitor at least that time to get there.
It might be an edge-case, but it's just another scenario out of many. I'm sure there are plenty of scenarios out there that add content via JS and won't be covered by an implementation like this 🤔

@zaguiini
Copy link
Contributor Author

zaguiini commented Mar 16, 2022

Hey @aristath,

For the use-case you described: the user/developer can still programmatically enqueue webfonts at will -- they'll know beforehand which ones they want to preload, so when it's fetched through AJAX, for example, the font-face declaration will be there already. I don't see a problem with that.

On a side note, though: the PRs that we're adding are in no way final. They could, and probably will, be iterated upon in the future. This PR is scanning for webfonts used in the default Gutenberg post types, which is about what we can do. It's really hard to give support to a million post types and ways to inject content since we do not know what the users/plugin developers are doing. We're adding a way to:

  1. automatically scan and enqueue webfonts that are located in the posts that Gutenberg/WP provides by default (post, pages, etc);
  2. exposing an API where plugin developers can hook into and register/enqueue webfonts at will.

I think we're headed in a good direction with this right now, and I don't think this is the final form as well. Let's go step by step. First, separate between registering and enqueueing. Second, scan the content we know how to scan and look for fonts. Third, account for any edge cases that might appear once the API is published. Curious to understand what you think about it.

@zaguiini zaguiini force-pushed the try/expose-enqueue-webfont-method branch 2 times, most recently from 88941bc to f763e10 Compare March 16, 2022 23:34
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from 9440eba to 7f7dde5 Compare March 16, 2022 23:54
@zaguiini zaguiini force-pushed the try/expose-enqueue-webfont-method branch from f763e10 to e497a0c Compare March 17, 2022 00:08
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch 2 times, most recently from 035093b to e1c4ea8 Compare March 17, 2022 00:15
@zaguiini zaguiini force-pushed the try/expose-enqueue-webfont-method branch from e497a0c to 5ab6da7 Compare March 17, 2022 00:49
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from e1c4ea8 to 35e6782 Compare March 17, 2022 00:52
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from 35e6782 to 64cc706 Compare March 17, 2022 16:13
@zaguiini zaguiini force-pushed the try/scan-content-for-webfonts-and-enqueue-them branch from 64cc706 to dee80c1 Compare March 17, 2022 16:36
@jeyip
Copy link
Contributor

jeyip commented Mar 22, 2022

We've since created an alternative approach that we find preferable to this PR. It can be found here. #39559

@zaguiini
Copy link
Contributor Author

Close in detriment of #39593.

@zaguiini zaguiini closed this Mar 22, 2022
@aristath aristath deleted the try/scan-content-for-webfonts-and-enqueue-them branch March 23, 2022 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants