Requests are expensive
Every additional request for data incurs a costly network roundtrip.
Requests are expensive (!)
Requesting unused data (like fetching 100 posts to iterate over them and fetch one) incurs expensive bandwidth costs (think mobile users).
REST conventions are purposefully limiting
Unlike SOAP, REST models requests around the primitive HTTP verbs and conventions. While limiting, it comes with many out-of-the-box benefits for scalability.
Components instead of arbitrary elements
Introduces a strict hierarchy and encapsulation into the frontend.
Different paradigm for the markup
Comparable to the change from procedural to object-oriented programming.
Many useful components provided as building blocks
State is immutable
The internal state model does not have setters.
Changes are done by dispatching actions
Every state change can be properly retraced.
Reducers compute modified state
A reducer is a function that takes current state and an action, and returns the adapted state as a result of this action.
Abstracted away in a separate @wordpress/data
package
Bridges the initial gap
React-based component on the client-side that retrieves its rendering output from the server-side.
Routes callback through a REST API controller
The component calls the /gutenberg/v1/block-renderer/{block}
controller, which in turn calls the block's render_callback
method.
Official reference documentation
wordpress.org/gutenberg/handbook/components/server-side-render
$args = [
'attributes' => [
'answer' => [
'type' => 'integer',
'default' => 42,
'minimum' => 0,
'maximum' => 8675309,
],
],
'render_callback' => 'render_serverside_block',
];
register_block_type( 'wcsea', $args );
function render_serverside_block( $attributes ) {
// We're using output buffering to render a view.
ob_start();
try {
include PLUGIN_DIR . '/views/wcsea-block.php';
} finally {
// Make sure we stop buffering again.
ob_end_clean();
}
return ob_get_clean();
}
<div class="wcsea-2018-block">
<p>The answer to life, the universe and everything is <?= esc_html( $attributes['answer'] ) ?>.</p>
</div>
Decouples persistence backend from other logic
All of your business logic is only coupled to a strict interface, not a concrete database implementation or similar.
A decoupled backend can easily be changed behind its interface
As long as you keep this interface intact, the changes you make to the backend will not ripple through to the rest of your code.
Opportunity for major changes or parallel tracks
You can now replace the direct database access with a REST API-based approach, or even use both at the same time.
interface BookRepository {
// The interface contains all methods you want
// to make available to your business logic as
// part of the abstraction.
/**
* Finds all available books.
*
* @param int $page Page offset to use.
*
* @return array Array of books grouped under
* a 'books' key.
*/
public function find_all( $page = 1 ) : array;
}
class WPDBRepository implements BookRepository {
// Specific implementations will be inter-
// changeable and not impact business logic.
public function find_all( $page = 1 ) : array {
$args = array(
'post_type' => 'book',
'posts_per_page' => 20,
'paged' => $page,
);
$query = new WP_Query( $args );
return array( 'books' => $query->get_posts() );
}
}
REST API allows you to bridge the gap between server and client
As a network communication protocol, it can cross the client/server boundary and pass along data.
It is a first requirement for a clean Gutenberg integration
Gutenberg was built from the ground up with the REST API in mind and offers many out-of-the-box features to simplify the data flow through REST resources.
class RESTfulBookRepository implements BookRepository {
public function find_all( $page = 1 ) : array {
$args = array( 'page' => $page );
$controller = new WP_REST_Posts_Controller( 'book' );
$request = new WP_REST_Request( '', '', $args );
// <- Permission checks should go in here.
$items = $controller->get_items( $request );
$books = rest_ensure_response( $items )->get_data();
return array( 'books' => $books );
}
}
Users spread across multiple environments
Your plugin will need to work with Gutenberg, the Classic Editor plugin or any odd combination of these two.
Reuse components to avoid maintenance nightmare
Having almost the exact same code running on these differing environments pays off in the long run with cheaper maintenance and faster iterations on new features.
import React from "react";
import PropTypes from "prop-types";
import { Provider as StoreProvider } from "react-redux";
import { Fragment } from "@wordpress/element";
import { Fill } from "@wordpress/components";
export default function Metabox( { settings, store, theme } ) {
return (
<Fragment>
<Fill name="YoastMetabox">
<SidebarItem renderPriority={ 9 }>
<StoreProvider store={ store }>
<SnippetEditor hasPaperStyle={ false }/>
</StoreProvider>
</SidebarItem>
// [...]
In the long run…
Control fragmentation
Tightly control the environments to support, and drop support as soon as it makes sense.
Keep your code base flexible
Abstractions allow you to move faster when Gutenberg evolves into unexpected directions. Be the first to make use of opportunities!
Properly embrace Gutenberg
Add integrations that take advantage of the UX that only Gutenberg can offer.
For a gradual move to Gutenberg...
ServerSideRender
componentI'm Alain Schlesser.
Follow me on Twitter:
@schlesseraOr visit my Personal Blog:
www.alainschlesser.com