Repository navigation
perf(theme): add a core web vitals baseline - #520
francoistibo wants to merge 2 commits into
Conversation
Revue perf backendTrès bon socle CWV dans l'ensemble (LCP / CLS / INP bien ciblés, README honnête sur ce qui reste par projet). Mon seul vrai point de vigilance est backend, et il est concentré dans I/O fichier répété, non cachéAujourd'hui, chaque appel de
Soit ~3-4 syscalls fichier + un read + de la regex par image. En boucle (ex. archive de 80 cartes avec placeholder), c'est un pattern N+1 sur le filesystem. Important : sur une infra où le web root / le thème est monté en réseau (NFS, EFS, montage partagé multi-front), chaque Pistes (par ordre de préférence)
Secondaire : Benchmark avant/après souhaitéAvant merge, j'aimerais un A/B
Critères : sur cache chaud, le coût doit être ~indépendant de N et Point annexe à mesurer
|
| 'before' => '', | ||
| 'after' => '', | ||
| 'default' => false, | ||
| 'is_lcp' => false, |
There was a problem hiding this comment.
Pour une utilisation avec ARI, il faut bien le laisser à false car c'est ARI qui gère automatiquement ce fetchpriority via la déclaration de sa taille d'image au bon format.
Le documenter ? gérer un warning ou autre ? ou bien le tester avec ARI et s'assurer que ça ne casse rien si c'est à true ?
| * | ||
| * @return void | ||
| */ | ||
| public function preload_fonts(): void { |
There was a problem hiding this comment.
ça fonctionne bien sur les fonts du dossier dist ? donc fonctionne dans un contexte fontsource ou font custom ? les fontsources sont aussi copiées dans le dossier dist
| continue; | ||
| } | ||
|
|
||
| // Empty alt marks a decorative image; omitting the attribute is not equivalent for AT. |
There was a problem hiding this comment.
Il y avait déjà un fix dans la fonction the_image pour avoir un alt à vide si on le force, sinon l'attribut était supprimé.
Ici c'est le même principe, sauf que c'est une nouvelle fonction pour appeler une image venant du thème c'est ça (avec les attributs width/height etc...) ?
| */ | ||
| add_action( 'wp', [ $this, 'register_assets' ] ); | ||
| add_action( 'wp_head', [ $this, 'preload_fonts' ], 1 ); | ||
| add_filter( 'get_custom_logo_image_attributes', [ $this, 'deprioritize_custom_logo' ], 20 ); |
There was a problem hiding this comment.
Utile ? car notre logo est généralement un svg, soit inline, soit venant du thème ou alors une image venant d'un champ ACF. Ce filtre se base sur quoi ?
There was a problem hiding this comment.
Voir avec @n-langle vu que ça touche à oneloop ?
|
Good job, merci @francoistibo :) |
|
@asadowski10 voilà une PR qui reprend ce que j'ai pu faire de générique en terme de perf sur Liora. y'a quasi la meme sur BBT. on va repasser sur tout ce qui touche a nos pratiques TD en réunion d'équipe, et je veux bien une petite review plugin dev ensuite |
|
@herewithme dans ce commit, Les dimensions des images statiques sont maintenant calculées au build et stockées dans dist/assets.json (imageDimensions) ; au runtime on lit le manifeste déjà en cache, donc plus de lecture fichier en boucle sur un thème buildé. Fallback fichier une fois par chemin/requête si l’asset n’est pas dans le manifeste. URI mémoïsée, sans double résolution child/parent quand il n’y a pas de thème enfant. |
Top, un bench avant/après ? :) |
Give projects opt-in LCP images, sized static images, a low-priority logo, idle JS init, and scroll-free animations so new themes start closer to good CWV scores. Co-authored-by: Cursor <cursoragent@cursor.com>
1498fe6 to
b82bd4f
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b82bd4f. Configure here.
| delta, | ||
| direction: { x: Math.sign(delta.x), y: Math.sign(delta.y) }, | ||
| } | ||
| } |
There was a problem hiding this comment.
Scroll direction lost across observers
Medium Severity
getScrollInfos() writes lastScroll on every call, so only the first IntersectionObserver callback in a turn keeps a real delta. Later observers (and destroy()) then see direction as 0. Translation presets use scrollInfos.direction.y on show/hide, so those animations get a wrong or empty offset when several rootMargin groups fire together — the translation preset’s random start range makes that common while scrolling.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit b82bd4f. Configure here.


Dotez les projets d'images LCP « opt-in », d'images statiques redimensionnées, d'un logo à faible priorité, d'une initialisation JavaScript en mode veille et d'animations sans défilement, afin que les nouveaux thèmes démarrent avec des scores CWV plus proches de la moyenne.
Résumé
get_the_image()(is_lcp) :fetchpriority="high",decoding="sync", pas deloading="lazy".fetchpriority="high"n'est jamais combiné avecloading="lazy".get_theme_static_image_markup()/the_theme_static_image():widthetheightlus dans le fichier du thème (SVG ou raster) pour limiter le CLS. Unaltvide est rendualt=""(image décorative) ;falseounullretire l'attribut.alt=""quand l'appelant le demande sur une image de la médiathèque, pour que les technologies d'assistance ignorent l'image.fetchpriority="low", pour qu'il ne concurrence pas la vraie image LCP.bea_theme_framework_preload_fonts. La liste est vide par défaut : seuls les fichiers réellement affichés au premier rendu doivent y figurer.Animationpar unIntersectionObserverpartagé. Les options (start,end,playOnce,hideOnReachEnd) et les callbacks (onInit,onShow,onHide,onDestroy) restent les mêmes.deferInitialization()pour lancer le JavaScript non critique au repos du navigateur (INP).robots.txt, cache, fonts, embeds tiers) dans le README.Plan de test
the_image()avec'is_lcp' => trueproduitfetchpriority="high",decoding="sync"et aucunloading="lazy".the_image()avec'alt' => ''produitalt="".the_theme_static_image()sur un SVG qui awidthetheightreprend ces attributs etalt="".fetchpriority="low".bea_theme_framework_preload_fonts, aucun<link rel="preload" as="font">n'est imprimé..js-animation-opacityreçoitis-visibleen entrant dans le viewport, et reste masqué avant.prefers-reduced-motionet l'impression désactivent toujours les animations.Note
Medium Risk
Touches front-page image attributes, scroll-driven animations (behavior may differ slightly from the old scroll-percent logic), and build output manifest shape; low security impact but worth regression-testing hero animations and static images after deploy.
Overview
Adds a Core Web Vitals baseline to the theme framework so new projects start closer to good LCP, CLS, and INP scores.
PHP / markup:
get_the_image()gains opt-inis_lcp(fetchpriority="high", noloading="lazy";decodingstays caller-controlled). Decorativealt=""is preserved on media library images. Newthe_theme_static_image()/ helpers outputwidth/heightfrom build manifestimageDimensionsindist/assets.json, with a per-request filesystem fallback.Performancehooks add opt-in font preload viabea_theme_framework_preload_fontsandfetchpriority="low"on the custom logo.AssetsreadsimageDimensionsand tolerates manifest keys that are not plain string paths.Build:
WebpackStaticImageDimensionsPluginwrites intrinsic sizes fordist/images/*intoassets.jsonat compile time (SVG parse + optionalsharpfor rasters).JS:
Animationdrops theoneloop.jsscroll observer loop for sharedIntersectionObserverinstances (fallback shows content when IO is missing). NewdeferInitialization()runs non-critical work on idle for INP.Docs: README documents theme-provided CWV helpers vs per-project cache, SEO, fonts, and embeds.
Reviewed by Cursor Bugbot for commit b82bd4f. Bugbot is set up for automated code reviews on this repo. Configure here.