WordPress / performance

Performance plugin from the WordPress Performance Group, which is a collection of standalone performance modules.
https://wordpress.org/plugins/performance-lab/
GNU General Public License v2.0
360 stars 98 forks source link

Appropriate preload value should be selected for video based on whether it is in the viewport #1592

Open westonruter opened 23 hours ago

westonruter commented 23 hours ago

I noticed that the default preload value for videos in the Video block is set to "Metadata":

Image

Nevertheless, this does not result in preload=metadata being added to the VIDEO tag in Gutenberg but rather no preload attribute at all. This leaves it up to the browser to decide what the default behavior is. In the worst case, the browser could decide the default is preload=auto which according to MDN, this "Indicates that the whole video file can be downloaded, even if the user is not expected to use it." This is not good as it means bytes are needlessly being downloaded. Nevertheless, Chrome's default is preload=metadata which is what the spec encourages browsers to use. When using preload=auto

On an example page that has a Video with a poster outside the viewport, the following is the impact on the total number of bytes downloaded for a video that is 59 MB in size:

preload=auto (4.5 MB) preload=metadata (1.5 MB) preload=none (0.9 MB)
Image Image Image

Note: The values of preload=auto and preload=metadata actually often seem to result in the same bytes being downloaded by Chrome. What is consistent, however, is that preload=none saves on a lot of bytes. Therefore, it may not make much of a difference setting preload=auto versus preload=metadata for videos in the initial viewport, but what surely will make a difference is to set preload=none for a video that doesn't appear in any initial viewport breakpoint.

The preload=none value should be automatically changed to preload=metadata (or preload=auto) when a video enters the viewport (via IntersectionObserver). This will ensure that the video is ready to play when the user sees it (similarly to https://github.com/WordPress/performance/issues/1590 which would start autoplaying when the video nears the viewport):

preload=none preload=metadata
Image Image

When a video is in all initial viewports, it should probably get preload=auto especially when it is the LCP element. ~It may even make sense to add fetchpriority=high preload links when it is the LCP element, particularly when the video has autoplay.~ (Update: This is not supported. See https://github.com/WordPress/performance/pull/1593.)

Note that the poster is getting downloaded automatically even though the video is not in the viewport. I've filed #1591 for this.

westonruter commented 23 hours ago

On a page on which the LCP element is an image which has fetchpriority=high and also has a video far below outside the viewport, I used benchmark-web-vitals to measure the impact of making an out-of-viewport video use preload=none as opposed to preload=metadata. I did not notice any consistent improvement, even with network throttling. So this may not readily improve LCP but it would reduce the weight of pages similarly to adding loading=lazy to images. In theory this could improve LCP since there would be less network contention when loading assets rendered in the initial viewport.

westonruter commented 22 hours ago

Setting out-of-viewport videos to preload=none and then setting to preload=metadata via an IntersectionObserver is also recommended as a way to Improve INP:

Image

Nevertheless, I don't think the default preload value is quite right as I've responded.

I think point 3 is meant to say:

  1. Set preload="none" on <video> and use an IntersectionObserver to set it to preload=metadata or preload=auto so that the video only downloads when the user comes close to it

Which is what I'm suggesting we implement here. Changing from preload=metadata to preload=none would probably not have as much of a performance improvement as changing from preload=auto to preload=none (although I don't see much of a difference between metadata and auto, at least in Chrome).