T233675: Audit startup JavaScript payload (Aug 2018—Sept 2019) | T233676: Audit default module payload (2019)
Objective
This task proposes to focus on the following theme for a quarter: Reduce use of @embed to only images that generally render above-the-fold.
Expected impact, based on "Size of stylesheets" at https://www.mediawiki.org/wiki/Wikimedia_Performance_Team/Page_load_performance:
- Improved visual progression for readers (first paint earlier, last paint same or better as today).
Rationale
Smaller stylesheets download quicker. The sooner the styles arrive to completion, the sooner the browser is allowed to start rendering the above-the-fold HTML it already got in its buffer.
By letting our icons load separately (in parallel with preload) I hope that the first paint (above-the-fold content and layout) can occur sooner than today.
The paint with the icons would still be at the same time as today, in browsers supporting Preload. In other browsers (shrinking population over time) icons would appear 1 RTT later than today, but still before the load event, given other loadevent-tracked sub resources taking at least 2 RTT as well.
In retrospect, this isn't really anything new. Most any major site today works the same way. GitHub, Google properties, Twitter, Facebook. They load at once with content and layout in their final resting place, but icons pop in later. Unlike layout FOUCs, these seem quite acceptable and not fundamentally different to how other images render in a browser. That is, the website logo or infobox images also appear separate from the text. Same for native applications as well.
Best practices
- If used in a styles-only module, the entire article will remain blank until the embedded image has been downloaded and processed. No text, no skin layout, nothing will appear. This the the absolute strongest form of blocking and critical path available on the web. As such, it requires equally strong rationale before using :)
Also, the styles queue varies between page-views which means users may have to download the same embedded icons multiple times. Without embedding, they enjoy the benefits of browser caching.
- If used in a JS module that also contains styles, the module will not be "ready" until the image is downloaded. This delays execution of other modules that depend on it, as well as any mw.loader promise, until the styles are downloaded, parsed, and added to the page (regardless of whether the CSS rules match).
This means if a module is lazy-loaded on-demand only where it is definitely needed, and the selector for the background image will definitely match, then using @embed does not waste bandwidth. But, you might still want to avoid it. For example, if a JS module contains a complex dialog framework that is only loaded when you are about to create a dialog, do you want the dialog to be visible sooner without the image first, or block any use of the dialog on the image being downloaded? If the dialog would look broken or incomplete without the image, then embedding might make sense. But, otherwise, best to avoid it still and allow progressive rendering.
Plan
- Remove unneeded use of @embed in MediaWiki core modules and WMF-deployed extensions.
- Determine whether we can improve the internals of @embed for the remaining use cases.
- Cost of parsing data URIs: Analyse the cost in browsers on various mobile devices / and OSes for downloading and parsing stylesheets with data URIs vs regular urls. Safari and Firefox were once known to parse the image binary data forcefully while processing the stylesheet, instead of skipping the data URI to only parse it when the CSS rule matches (like browsers already do for regular urls).
- Compressibility of data URIs: Even if data URIs are around the same length as the path URL, the path urls should compress much better in practice given most of the paths are similar, with only the base name differing. This should very significantly shrink icon packs.
- If useful, implement @preload
- Migrate from @embed to @preload.
- Coordinate roll out with performance survey (@Gilles), and attempt to A/B test.