Modify apiFetch to only rely on server-preloaded data for the first request
See original GitHub issueBug Description
We currently preload data for several API endpoints so that no requests on pageload are necessary:
- connection data for
core/sitestore - authentication data for
core/userstore - module information for
core/modulesstore - settings for all
modules/*stores with settings
There is a problem with that approach because the apiFetch middleware will always have these API requests resolve with this data, even later during the app lifecycle where things might have changed. For example, when you activate a module, core/user authentication data should be refetched. We don’t use this anywhere yet so it’s not critical, but in the current stage it will not work since it would still not issue an API request and instead rely on the server-preloaded data which at that point will be stale.
We should modify this behavior (e.g. by customizing the behavior of the middleware or potentially implementing our own version of it) so that it only uses the preloaded data for the initial request(s). It should just be one request, but in theory there could be a race condition where the data is requested multiple times. What would probably make sense is to “invalidate” the preloaded data after it is first used, potentially with some timeout of 500ms or so to cater for the race condition (maybe that’s not even worth doing).
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
API preloaded data handling
- Server-preloaded data should only be used for
apiFetchrequests for the initial request(s). For subsequent requests, the data should be invalidated so that the actual API request will be fired.- Preloaded data should be invalidated as soon as it’s used once for a request.
- Theoretically this would be a problem if two similar requests were fired at about the same time, but the way that datastore resolvers work and the way we’re using them make this practically irrelevant.
- Since it could happen that no such request happens on pageload, we should set an arbitrary threshold of 1000ms (once we have a PR, let’s test whether that value works well or whether we should adjust) after which preloaded data should get invalidated regardless of whether a request has been made that applies to it.
- Preloaded data should be invalidated as soon as it’s used once for a request.
- Server-preloaded data should be used independently of whether a request uses caching or not (other than in the original IB and #1692); its only purpose is to avoid an API request right after pageload (which is common to be caused for all of the JS stores that rely on API requests where we preload data).
Module store adjustments
- The
core/modulesstore should, as part of thesetModuleActivationaction rely on thecore/userstore’s authentication infrastructure instead of just refetching a current API response. - Module data should be preloaded on the server via the
google-site-kit/v1/core/modules/data/listREST endpoint.
Implementation Brief
Custom preloading middleware
- Create a Site Kit specific implementation of
@wordpress/api-fetch’spreloadingMiddlewareinassets/js/googlesitekit/api/middleware/preloading.jswhich exports a customdefault createPreloadingMiddleware; - In
assets/js/api-fetch-shim.js, importcreatePreloadingMiddlewarefrom our internal module, rather than the core non-shim module.
Custom preloading middleware implementation
- If there is preloaded data for a
GETrequest, remove that data for future requests before returning it for this initial request.
https://github.com/google/site-kit-wp/blob/9acf11d915c894b7a85e6016216cf4bc9767bd99/assets/js/googlesitekit/api/middleware/preloading.js#L56-L59 - When the middleware is invoked for the first time, set a timeout of
1000ms- When the timeout callback is run, set a flag outside of the middleware which indicates that the middleware has been invalidated
- On subsequent invocations, if the above flag is set, the middleware should immediately call
next( options ), essentially bypassing its main logic
Module store adjustments
- In
assets/js/googlesitekit/modules/datastore/modules.js:- Change the
REFETCH_AUTHENTICATIONcontrol to be come a registry control, which calls thecore/userstore’sfetchGetAuthentication(). - Move yielding the
REFETCH_AUTHENTICATIONinto thesetModuleActivationaction right after thefetchGetModulescall in the clause, as it is right now unnecessarily duplicated.
- Change the
- In the PHP
Modulesclass, addgoogle-site-kit/v1/core/modules/data/listto the list of preloaded route paths.
QA Brief
Changelog entry
- Fix usage of
apiFetchwith a custom middleware to only rely on preloaded data for initial requests on pageload.
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (4 by maintainers)

Top Related StackOverflow Question
Reviewed the updated IB here and it sounds great. Sounds like we’re all in agreement so let’s move this to execution 🙂
@aaemnnosttv I like the approach of using a timestamp when
useCacheis false, and by deleting the cached data upon returning it, we pretty much have the “one-time usage” we want. IB ✅