Page MenuHomePhabricator

Native image lazyloading should not apply to images above the fold
Open, MediumPublicFeature

Description

Feature summary:
Images above the fold should be eagerly loaded, regardless of $wgNativeImageLazyLoading.

Use case(s):
$wgNativeImageLazyLoading adds a loading="lazy" attribute to all thumbnail's <img> elements on the page.
This decreases the perceived loading and the Largest Contentful Paint (LCP) time of the page.

Potential solutions include:

  • Allow user to define whether a thumbnail should be eagerly loaded through the image syntax in wikitext
  • Do not add the lazyloading attribute to the first non icon image rendered
  • Do not add the lazyloading attribute to images above certain height of the page

Benefits:

  • Reduce perceived loading time for users
  • Reduce LCP

Event Timeline

Thanks @alistair3149 for raising this as a suggestion.

I believe your hypothesis, that indescrimitely adding loading=lazy to all images would harm paint timing such as LCP, is likely to be true for Wikipedia articles. This is consistent with the research that our team is aware tracking in the industry (such as the fine folks of WordPress.org who wrote about this), and is one of several reasons why we have not (yet) taken the final steps of T148047: Desktop MediaWiki should be able to lazy load images.

Having said that, we should take into account the unique composition and performance characteristics of Wikipedia articles as well. For example, one of the things that we learned from our continuous synthetic tests is that for us the "Largest Contentful Paint" is actually attributed in Chrome to the first <p> paragraph, and usually not the first image (e.g. infobox thumbnail). This makes it less certain how the lazy loading attribute on the first image will affect LCP.

However, even if it does not benefit LCP, I believe it likely would not negatively affect it either, and might still positively impact Last Visual Change (the time to visual completion above-the-fold as measured in WebPageTest) and PLT (Page Load Time, overall); which we consider key metrics (docs).

To my knowledge we have not (yet) run a speed test, in WebPageReplay or otherwise, to confirm this hypthesis one way or the other. We'd likely want to do that and then decide whether and how to implement this in MediaWiki core.

I note that, due to the specifics of the wikitext Parser, the desire for stateless internals, and the various special cases of images that don't count as proper images (e.g. icons in message templates) - it is not trivial to implement. We don't currently have much precedence for post-processing modifications on desktop, and the experience we do have with the current MobileFormatter implementation comes at a significant performance penalty (grafana).

Krinkle triaged this task as Medium priority.May 17 2022, 8:57 PM
Krinkle edited projects, added Performance-Team (Radar); removed Performance-Team.

I'm triaging this task to our radar for the time being, and have instead hoisted the parent task as tracking task for our "Future Goals" column as reminder to for our team to push for evaluating this in an upcoming quarter. There is no commitment at this time as for which year that would be.

@Krinkle Thanks for the through insights, it's very helpful!

You're correct that this might not have as big as impact on regular Wikipedia articles as the paragraph element is usually the LCP on both desktop and mobile (MobileFrontend moves infobox below the leading paragraph). On WMF wikis, sometimes main page and site notices (funding banner especially) have images large enough that contribute to LCP. And of course there are always third party wikis.

In the same class where the loading attribute is added to the image (ThumbnailImage.php), I see things like priority hint and self::$firstNonIconImageRendered, in which I'm not entirely sure what its purposes are, there wasn't a lot of information from the previous tasks and the documentation. My assumption is that it has some sort of way to rank the importance of assets, maybe it can be repurposed for image lazyloading?

Thanks @alistair3149, I forgot about that. That's a left-over from T230808 and T216598, which is currently inactive. I had mentally removed this code already, but we clearly have not yet. Hereby filed at T308621.

Nonetheless, you're right that this could be used in the future for something similar indeed. I do note however that 1) the definition of "first non-icon image" for that experiment was fairly uninformed and ad-hoc for that particular experiment and is significantly different from the more nuanced logic we use in the MediaViewer or PageImages extension which something non-experimenetal should likely be more similar to, and 2) ThumbnailImage.php is part of the legacy parser and Parsoid, the new parser, handles this notably different with generally a principled choice not to allow such global state.

Thanks for the quick reply.

With the upcoming parser changes this task is certainly stalled.

Just for LCP purposes, icons can possibly be filtered out from images with a width/height threshold, which only allow the first (or few?) image large enough to pass through as they might contribute to LCP. My assumption is that loading metrics might be slightly better than the current implementation, what are your thoughts on this?

Change 793008 had a related patch set uploaded (by Mainframe98; author: Mainframe98):

[mediawiki/core@master] Remove experimental Element Timing experiment

https://gerrit.wikimedia.org/r/793008

[…] My assumption is that loading metrics might be slightly better than the current implementation, what are your thoughts on this?

My thoughts are that we should measure it and find out :)

Func subscribed.

I turned on this config on my site recently, and noticed that the Google PageSpeed Insights tool complaining about LCP issues due to first featured images being lazy-loaded.

I think we can integrate the PageImage extension with this config and remove the load attr when the image is chosen as the page image.

Change 961507 had a related patch set uploaded (by Func; author: Func):

[mediawiki/core@master] Linker: Support lazy-loading param for the makeImageLink() method

https://gerrit.wikimedia.org/r/961507

Change 961508 had a related patch set uploaded (by Func; author: Func):

[mediawiki/extensions/PageImages@master] Prevent lazy-loading of the page image

https://gerrit.wikimedia.org/r/961508

Change 961508 abandoned by Func:

[mediawiki/extensions/PageImages@master] Prevent lazy-loading of the page image

Reason:

https://gerrit.wikimedia.org/r/961508

Change 961507 abandoned by Func:

[mediawiki/core@master] Linker: Support lazy-loading param for the makeImageLink() method

Reason:

https://gerrit.wikimedia.org/r/961507

Hoping to bring this to attention for more people and continue the discussion.

On the patch above, @Krinkle mentioned that

This should be fixed to work automatically. I don't think we need to expose this to wikitext or otherwise require content changes. At the moment the feature in question is not used, and until it is, this problem is not yet urgent. WordPress has done some groundwork here in terms of automatically setting this correctly based on the Largest Contentful Paint metric.

According to the related patches for WordPress, the one approach that might apply to our case here is to hardcode a threshold of images to skip lazyloading. It might not be the prettiest solution. However, making that into a config flag and combines with some rules to filter out the icons, it can be a decent stopgap solution.

The PageImage idea that @Func introduced is interesting as well, though PageImages might not always pick the right image on third-party wikis and there isn't a way to override the selection from PageImages.

There are some additional discussions and a technical document very recently on improving LCP image accuracy on WordPress. Sadly many parts of it is out of my depth so I hope that this helps as a reference.