Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apiFetch preloading middleware ships 1MB+ of redundant REST data #27370

Closed
jsnajdr opened this issue Nov 30, 2020 · 4 comments
Closed

apiFetch preloading middleware ships 1MB+ of redundant REST data #27370

jsnajdr opened this issue Nov 30, 2020 · 4 comments
Labels
Core REST API Task Task for Core REST API efforts Needs Dev Ready for, and needs developer efforts [Type] Performance Related to performance efforts

Comments

@jsnajdr
Copy link
Member

jsnajdr commented Nov 30, 2020

Describe the bug
The apiFetch preloading middleware can easily ship more than 1MB of redundant data on the initial load. Only few kilobytes or even bytes out of that are ever really used by the app.

To reproduce
Steps to reproduce the behavior:

  1. Open block editor for a post, i.e., an URL like /wp-admin/post.php?post=921&action=edit
  2. Look at the HTML response in devtools and find a script that calls wp.apiFetch.createPreloadingMiddleware
  3. Look closely at the data it preloads and how big they are

Expected behavior
The preloaded data contain more or less only the information that the editor really uses, and don't have a 100x or even 1000x overhead.

Actual behavior
On a testing site with Jetpack and WooCommerce, two popular plugins that register quite a few REST routes, I see that:

The post.php?post=id&action=edit response is 1.7MB (174kB compressed) of HTML and inline CSS and JS.

The wp.apiFetch.createPreloadingMiddleware call has an argument that's 930kB big.

The preload data for the / path contain a few bytes of information that the editor may really want (site name, description, URL, time zone) and then, in the body.routes field, a complete meta-description of all registered REST routes.

The preload data for the OPTIONS /wp/v2/media request are 17kB of mostly body.endpoints data with detailed descriptions of the supported GET and POST request params, while the relevant information is just one line:

headers: { Allow: 'GET, POST' }

that says whether the current user is allowed to POST to /wp/v2/media, i.e., has upload permissions. See also #4155 that added the OPTIONS /wp/v2/media preload specifically and #12378 where @noisysocks introduced a general-purpose canUser selector that uses OPTIONS requests and their Allow response header to detect capabilities.

The signal-to-noise ratio of these OPTIONS responses is very low, on the "20 bytes out of 20 kilobytes" scale.

Editor version (please complete the following information):

  • tested on WordPress 5.5.3 with the default block editor (no Gutenberg plugin), but even the latest bleeding edge has the same issue, too.
@gziolo gziolo added [Type] Performance Related to performance efforts Core REST API Task Task for Core REST API efforts labels Nov 30, 2020
@noisysocks
Copy link
Member

Good catch @jsnajdr. Could be good to tackle this as part of a rethink of how we do preloading. There's some issues with our current approach, e.g. #24672 (comment).

@jsnajdr
Copy link
Member Author

jsnajdr commented Dec 7, 2020

@noisysocks That issue in #24672 (comment) where the preloaded data would be returned also on a second fetch, although we know it's been updated on the server and the preloaded copy is stale, has been fixed since. Just a month later, #25550 made the response be used only once.

It would be nice to preload the data store state rather than the REST response. But I'm afraid that's viable only on a Node.js server, where exactly the same data store can be instantiated and populated on the server, and then sent over to the browser as a serialized JS value. With a PHP backend, it's much more difficult to do right.

The entire preloading middleware could be replaced with preload directives:

<link rel="preload" href="https://example.blog/wp/v2/" as="fetch">

with a very similar behavior. The preloaded response is used only by the first fetch. A second one will always issue a fresh network request.

To manage the size of the responses, it would be great if we could enumerate the specific fields we are interested in. WP.com-specific REST endpoints support a fields query arg. I'm not sure about the Core REST APIs.

@TimothyBJacobs
Copy link
Member

Yeah, the simplest fix for this would be to use ?_fields.

@noisysocks noisysocks added the Needs Dev Ready for, and needs developer efforts label Feb 8, 2021
@jsnajdr
Copy link
Member Author

jsnajdr commented Apr 14, 2022

Fixed in #39256.

@jsnajdr jsnajdr closed this as completed Apr 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core REST API Task Task for Core REST API efforts Needs Dev Ready for, and needs developer efforts [Type] Performance Related to performance efforts
Projects
None yet
Development

No branches or pull requests

4 participants