-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Defer until wp.api has initialized before attempting to use Backbone models #1245
Conversation
These are not the only places we're using the backbone client, we use it also in: effects, tags, categories, featured image I think we should try to find a global solution to this. Anyway, using the backbone client is not so scalable, we're using it for consistency but I think, we should discuss it broadly and probably avoid using in, in favor to more declarative approach (for example a |
@youknowriad curious why you say that using the backbone client "is not so scalable"? |
Some context here: #907 (comment) Simple question since I'm probably missing some context too:
I see several issues with the backbone client:
Edit: Worth nothing that we're moving away from a similar client in Calypso to enable advanced features like caching, batching, replays, ... |
A simple, declarative way to handle the built in WordPress object types and their idiosyncrasies (writing wp.api.models.Post makes it pretty clear by looking at the code that you are dealing with a post). It also handles objects with a parent relationship (revisions), trashable objects, and API responses with
It also accepts a localized schema, if we localize the schema no additional ajax call is required, and the init call is essentially synchronous/will return immediately. It needs an init to set up the data types, which is what makes it useful. the init is called automatically when the client loads, the main thing you need to do is wait for it to complete - see https://developer.wordpress.org/rest-api/using-the-rest-api/backbone-javascript-client/#waiting-for-the-client-to-load.
batching is not supported by the WP-API currently, if it does become supported, that support will be added to the core wp-api client as well. why would you want to rebuild that outside wp-core if gutenburg is destined for core? replays - not sure what you mean by that, but if you are talking state replays, that seems like a higher level functionality we would handle in redux middleware? caching of callbacks in localstorage or another storage mechanism is dead simple, something like this makes it plug and play: https://github.com/SaneMethod/jquery-ajax-localstorage-cache
these are created on a separate namespace for legacy reasons. the client supports multiple endpoints, you would just need to call init a second time specifying the oembed endpoints.
That is fine for Calypso, however this is for core and i'd much rather see us enhance the core client to support the features you need so everyone can benefit from them rather than re-inventing existing functionality. Also worth noting that while Backbone uses jQuery.ajax by default, it is not dependent on it, you can readily swap this out with fetch or another polyfill. |
I agree this is a good feature and this should be backed in the HTTP layer (the backbone client here) 👍
This is subjective and I agree that's it's a nice approach when using Backbone as a framework but when we talk about unidirectional data-flow, single store (redux) ... this is not the recommanded practice, the state should ideally contain plain JS objects and any async call should be baked into async action creators. Having such methods in the collections and models is not really a good practice here.
Or retries: I mean re-trigger the requests on errors (with threshold config, network detetion and stuff like that)
Exactly, and if we avoid using a model based HTTP layer and use a generic layer, this middleware could be written easily
I was thinking about memory caching (store): Something to answer these questions:
I totally agree and that's why we're using it and I didn't suggest removing it now but more having a discussion later (in js meetings), but the more we move towards Gutenberg Like approaches with a single data store, unidirection data-flow, the more we'd need to rethink the client. |
209865e
to
7780764
Compare
@youknowriad thanks for pointing out the other instances. I realized that the approach I was taking wasn't ideal and we should just defer initializing the editor in the first place until the Backbone client has finished initializing. I've replaced previous commit in this branch with this change. |
@adamsilverstein Is it discouraged to localize the schema as you'd mentioned? It's not entirely clear from the documentation, except from the |
This might not be the right place to discuss needs around the API client, and am not advocating it being replaced, but a couple specific pain points encountered so far include:
Related: #902 |
In any case, I think this should be merged because it fixes the editor from being completely broken. We can revisit the approach for interfacing with the UI later. |
I tend to agree with @westonruter. Obviously, the UX regression here is not great, but we should get this merge to fix the bug (I already saw at least 3 reports of a white page). So, if I understand properly the delay would be noticeable only on the first load? |
@aduth I would actually encourage localizing the schema, especially given the wp-admin context. We leave this off by default because it adds additional weight/data to the page and might be unexpected by developers enqueueing the script. I will prepare a PR to localize the schema for Gutenburg - no other code will need to change, and we should still merge @westonruter's PR - the main difference is that the deferred will resolve immediately, without requiring an Ajax callback. In regards to mocking/testing, the approach we use in core would be applicable (especially after a core merge) - see https://core.trac.wordpress.org/browser/branches/4.8/tests/qunit/fixtures/wp-api.js for the js guts - in short, we override Backbone.ajax to returned the mocked data. We generate the mocked data in PHP unit test to ensure it is current with the actual API responses, see https://core.trac.wordpress.org/browser/branches/4.8/tests/phpunit/tests/rest-api/rest-schema-setup.php for the details. I agree actions should remain pure to keep them testable and I will take a look at the approaches you linked to try to understand how you push the network requests 'to the edge'. I'd like to understand how that works and see where it differs from how we would use wp-api. |
@aduth - I reviewed the approach used the Data Layer in Calypso and I think we could likely use a similar middleware approach here, keeping the client request in the middleware layer. I've also seen a similar approach where the middleware returns a promise, letting you act later on the asynchronous event completion. |
@youknowriad it could only be noticeable for the first time the user accesses the Gutenberg editor if the WP-API has never been loaded yet in the current browser session, such as somewhere else on the WP install. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would rather see schema localized, but let's defer that to a subsequent pull request (ideally with issue to track).
I don't like this approach very much. Coupling editor initialization with |
Agreed. This is just a stop-gap to prevent the white screen of death in the immediate term. |
Fixes #1235.
The first time the WP-API Backbone client is loaded in the browser, the REST API schema is fetched from the server and then stored in
sessionStorage
. As such, the Backbone models and collections are not available for such initial loads. To ensure they are available, thewp.api.init()
promise should first be resolved. Issue can be replicated by doingsessionStorage.clear()
and then reloading the Gutenberg editor.