3.19 Should preload fonts using @import
Describe the bug Fonts using @import are not preloaded.
To Reproduce Steps to reproduce the behavior:
- Install and activate WPR 3.19.
- Enable Preload Fonts & Self-host Google Fonts.
- Visit page template using GF above the fold via @import ( i.e. https://rocketlabsqa.ovh/preloadfonts_import/, preloadfonts_import.php template).
- Clear the cache and revisit the page.
Expected behavior Above the fold fonts using @import should be preloaded, too.
Note: Issue related to #7241 .
Screenshots If applicable, add screenshots to help explain your problem.
This issue has nothing to do with WP Rocket, but rocket scripts.
Scope a solution
In here, we could edit the function with something like:
getFontFaceRules() {
const stylesheetFonts = {};
// Helper to recursively process a stylesheet and its imports
const processSheet = (sheet, seenSheets = new Set()) => {
if (!sheet || seenSheets.has(sheet)) return;
seenSheets.add(sheet);
let rules;
try {
rules = sheet.cssRules || [];
} catch (e) {
// CORS or inaccessible stylesheet
this.logger && this.logger.logMessage(e);
return;
}
for (const rule of rules) {
// Recursively process @import rules
if (rule.type === CSSRule.IMPORT_RULE && rule.styleSheet) {
processSheet(rule.styleSheet, seenSheets);
} else if (rule instanceof CSSFontFaceRule) {
const src = rule.style.getPropertyValue('src');
const fontFamily = rule.style.getPropertyValue('font-family')
.replace(/['"]+/g, '')
.trim();
const weight = rule.style.getPropertyValue('font-weight') || '400';
const style = rule.style.getPropertyValue('font-style') || 'normal';
if (!stylesheetFonts[fontFamily]) {
stylesheetFonts[fontFamily] = {
urls: [],
variations: new Set()
};
}
const urls = src.match(/url\(['"]?([^'"]+)['"]?\)/g) || [];
urls.forEach((urlMatch) => {
let rawUrl = urlMatch.match(/url\(['"]?([^'"]+)['"]?\)/)[1];
// Reconstruct url to absolute if stylesheet is not internal.
if (sheet.href) {
rawUrl = new URL(rawUrl, sheet.href).href;
}
const normalizedUrl = this.cleanUrl(rawUrl);
if (!stylesheetFonts[fontFamily].urls.includes(normalizedUrl)) {
stylesheetFonts[fontFamily].urls.push(normalizedUrl);
stylesheetFonts[fontFamily].variations.add(JSON.stringify({
weight,
style
}));
}
});
}
}
};
Array.from(document.styleSheets).forEach(sheet => processSheet(sheet));
Object.values(stylesheetFonts).forEach(fontData => {
fontData.variations = Array.from(fontData.variations).map(v => JSON.parse(v));
});
return stylesheetFonts;
}
This should ensure to get the @import as well sent to the backend.
Efforts
S
LGTM
Thanks @Miraeld indeed, this is to be tackled on the beacon processing part in getFontFaceRules method, though Implementation might differ from what is proposed in grooming.
@MathieuLamiot Should we move the issue to Blocked for the moment or just remove it from this sprint ?
Is there a blocker? Otherwise, you can move it to ToDo and to the next sprint.