Skip to content

Fix #7417: Preload fonts external domains #7519

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

Merged
merged 11 commits into from
Jul 31, 2025

Conversation

Miraeld
Copy link
Contributor

@Miraeld Miraeld commented Jul 21, 2025

Description

Fixes #7417
This enhancement transitions WP Rocket's font preloading from a hardcoded allowlist approach to an exclusion-based model for external font processing. This change allows WP Rocket to process fonts from all external domains by default, while providing mechanisms to exclude problematic domains.

Type of change

  • Enhancement (non-breaking change which improves an existing functionality).

Detailed scenario

What was tested

Automated Testing:

  • ✅ Unit tests for DynamicLists::get_external_font_exclusions() method
  • ✅ Integration tests for Subscriber::get_external_font_exclusions() filter method
  • ✅ PHPStan static analysis passed
  • ✅ Code syntax validation

Manual Testing:

  1. Filter Functionality: Verified that the rocket_external_font_exclusions filter properly merges developer exclusions with dynamic list exclusions
  2. Beacon Data: Confirmed that external_font_exclusions array is correctly passed to the JavaScript beacon via rocket_beacon_data
  3. Dynamic Lists Integration: Tested that exclusions from the dynamic lists system are properly retrieved and merged
  4. Backward Compatibility: Ensured existing font preloading functionality remains unaffected

How to test

Testing Steps

  1. Basic Functionality Test:
<?php
// Add this to functions.php or a plugin
add_filter('rocket_external_font_exclusions', function($exclusions) {
    $exclusions[] = 'problematic-font-domain.com';
    return $exclusions;
});
  1. Verify Beacon Data:
  • Load any page on the frontend
  • Open browser developer tools → Console
  • Execute: console.log(rocket_beacon_data.external_font_exclusions)
  • Should display array including your excluded domain
  1. Dynamic Lists Integration:
  • Add external_font_exclusions to the dynamic lists data
  • Verify exclusions appear in beacon data without custom filter

Technical description

Documentation

This pull request introduces significant changes to improve font processing and external font exclusion handling in the wpr-beacon.js file and related backend logic. It removes unnecessary methods and constants, adds a new configuration for excluding external fonts, and includes extensive test coverage for the new functionality.

Frontend Changes:

  • Removed the EXCLUDED_TAG_NAMES constant and associated methods (canElementBeStyledWithFontFamily and canElementBeProcessed) from assets/js/wpr-beacon.js to simplify the font processing logic. [1] [2] [3]
  • Updated the external font processing logic to use a configurable list of exclusions instead of hardcoding domains, improving flexibility. [1] [2] [3]

Backend Changes:

  • Added a new filter, rocket_external_font_exclusions, to allow dynamic configuration of external font exclusions. This was implemented in Frontend/Controller.php and Frontend/Subscriber.php. [1] [2] [3]
  • Added a method get_external_font_exclusions in DynamicLists.php to retrieve external font exclusions from dynamic lists.

Test Coverage:

  • Added unit, integration, and fixture-based tests to validate the functionality of external font exclusions in both Frontend/Subscriber and DynamicLists. [1] [2] [3] [4]

New dependencies

None

Risks

None

Mandatory Checklist

Code validation

  • I validated all the Acceptance Criteria. If possible, provide screenshots or videos.
  • I triggered all changed lines of code at least once without new errors/warnings/notices.
  • I implemented built-in tests to cover the new/changed code.

Code style

  • I wrote a self-explanatory code about what it does.
  • I protected entry points against unexpected inputs.
  • I did not introduce unnecessary complexity.
  • Output messages (errors, notices, logs) are explicit enough for users to understand the issue and are actionnable.

Miraeld added 3 commits July 21, 2025 07:41
- Introduced a filter for external font domains to exclude from processing in the Controller.
- Added a method in Subscriber to retrieve external font exclusions for beacon configuration.
- Implemented a method in DynamicLists to get external font exclusions from dynamic lists.
@Miraeld Miraeld requested a review from a team July 21, 2025 05:57
@Miraeld Miraeld self-assigned this Jul 21, 2025
@Copilot Copilot AI review requested due to automatic review settings July 21, 2025 05:57
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR transitions WP Rocket's font preloading from a hardcoded allowlist approach to a flexible exclusion-based model. The change allows processing of fonts from all external domains by default while providing mechanisms to exclude problematic domains through filters and dynamic lists.

  • Removes hardcoded external font domain allowlist and tag name exclusions from JavaScript
  • Adds configurable external font exclusions via rocket_external_font_exclusions filter
  • Integrates dynamic lists system for centralized exclusion management

Reviewed Changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
assets/js/wpr-beacon.js Removes hardcoded exclusions and implements configurable external font filtering
inc/Engine/Media/PreloadFonts/Frontend/Controller.php Adds external_font_exclusions to beacon data via filter
inc/Engine/Media/PreloadFonts/Frontend/Subscriber.php Implements filter handler for external font exclusions
inc/Engine/Optimization/DynamicLists/DynamicLists.php Adds method to retrieve exclusions from dynamic lists
tests/* Comprehensive test coverage for new functionality
Comments suppressed due to low confidence (1)

tests/Integration/inc/Engine/Media/PreloadFonts/Frontend/Subscriber/getExternalFontExclusions.php:3

  • The namespace path inc\Media\PreloadFonts doesn't match the actual class path inc\Engine\Media\PreloadFonts. This should be WP_Rocket\Tests\Integration\inc\Engine\Media\PreloadFonts\Frontend\Subscriber.
namespace WP_Rocket\Tests\Integration\inc\Media\PreloadFonts\Frontend\Subscriber;

Copy link

codacy-production bot commented Jul 21, 2025

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for 2bc3b6e1 83.33% (target: 50.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (2bc3b6e) Report Missing Report Missing Report Missing
Head commit (2a2d7c6) 40056 17651 44.07%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#7519) 6 5 83.33%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

Copy link
Contributor

@jeawhanlee jeawhanlee left a comment

Choose a reason for hiding this comment

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

We'll need to test this PR with templates having numerous external styles that are not font styles. I worry about useless fetch request for external styles. Maybe this is an edge case.

@hanna-meda
Copy link
Contributor

hanna-meda commented Jul 30, 2025

Thank you, @Miraeld, for this PR.

Testing Notes so far:
• External font exclusions by filter will work only for domains that WP Rocket successfully preconnects to. Currently we have open issue related to preconnect: #7408
Tested using: https://rocketlabsqa.ovh/preloadfonts_multiple_external_fonts2/ with the following filter enabled:

add_filter( 'rocket_external_font_exclusions', function( $exclusions ) {
    $exclusions[] = 'fonts.bunny.net';
    $exclusions[] = 'cdn.jsdelivr.net';
    $exclusions[] = 'fonts.cdnfonts.com';
    $exclusions[] = 'cdnjs.cloudflare.com';

    return $exclusions;
});

As a result, only the external fonts from bunny.net and fonts.cdnfonts.com are actually excluded — these being the only domains from the filter list that WP Rocket was able to preconnect to.
Note: We can still exclude these domains directly from BE in such case.
cc @DahmaniAdame

Screenshot 2025-07-30 at 18 35 04

• Fontshare Case (shared in Slack thread):
The CSS returned includes access-control-allow-origin: https://api.fontshare.com, which blocks the fetch request due to CORS restrictions.
Conclusion: It’s best to exclude Fontshare for now. As a future enhancement, we could consider adding a fallback mechanism when a CORS issue is detected, to improve font loading coverage.

• External fonts injected via <script> and used below the fold, will still be preloaded, but only if the fonts are hosted on domains other than Google Fonts (e.g. Bunny Fonts). < to be handled in separate GH #7541

Copy link
Contributor

@hanna-meda hanna-meda left a comment

Choose a reason for hiding this comment

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

QA done. All tests are passing.
testrail-report-749.pdf

@hanna-meda hanna-meda added this pull request to the merge queue Jul 31, 2025
Merged via the queue into develop with commit c57ae02 Jul 31, 2025
15 checks passed
@hanna-meda hanna-meda deleted the enhancement/7417-preload-fonts-external-domains branch July 31, 2025 16: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.

3.19: Preload fonts external domains
3 participants