WordPress – Preparing to Power a Single Page Application

WordPress – Preparing to Power a Single Page Application

John Hewick

So now the REST API is part of the WordPress core, the CMS is opened up, not just to developers but to anyone who is interested in creating a frontend for a new website or for an app. This can be done while incorporating the easy-to-use WordPress admin panel.

PHP is a bit of a rough animal when it comes to templating and takes a lot of work to get it to create something masterful on the frontend. With the REST API integration, it is now feasible to render the front end entirely using JavaScript or another, easier language. This improves the potential for interactivity and creativity immensely.

If you decide to use the REST API, you should consider running the frontend on a node.je server, one which is completely different to the Apache or nginx server that you’ll be using to power the WordPress site itself.

How to Approach the Single Page App

If you usually work with WordPress, this might be a whole new way of doing things for you. Using basic JavaScript and jQuery’s AJAX library should make it easier to follow.

If you use Node and Express, it will look all sorts of wrong to you. However, Express simply allows WordPress-esque permalinks sans 404s. It also makes it easier to show you the basic concepts I’m working with.

Getting Started

Once upon a time, you’d need to install the REST API plugin, but the functionality has now been added to the WordPress core, making it even easier to design JS frontend sites and mobile apps.

Cross Origin Restrictions

When you run a separate front- and backend, you could run into issues with the cross-origin restrictions. These security restrictions are there so that sites can’t load with content from more than one domain. This means that AJAX requests fail when trying to request data from another separate domain. You can get around this using the correct cross resource origin sharing (CORS) headers.

CORS headers mean that selected sites can access your site. We can set up our site with CORS headers which apply to the REST API output. CORS headers must be output before HTML content. This can be done using the json_serve_request filter.

You could try allowing requests from any origin using this code:

add_filter( ‘json_serve_request’, function( ) {

header( “Access-Control-Allow-Origin: *” );


This might be easiest but it certainly isn’t the best option. If you replace the asterisk with a URL, that site only will be able to access the REST API. However, you can only use one CORS header. This means if you want multiple sites to have access, the referring site will need to be detected before you set the header.

This can be done if you define the array of acceptable domains and checking that the origin domain is there.

You can check to see if the super global $_SERVER has the key ‘HTTP_ORIGIN,’ which will contain the domain of the site that is making the request.

Here’s how:

add_filter( ‘json_serve_request’, function( ) {

$domains = array( ‘http://torquemag.io’, ‘http://wordpress.org’ );

if( isset( $_SERVER[‘HTTP_ORIGIN’] && in_array( $_SERVER[‘HTTP_ORIGIN’], $domain ) ) ) {

$domain = $_SERVER[‘HTTP_ORIGIN’];

header( “Access-Control-Allow-Origin: {$domain}” );



If the URL request is in the array of allowed domains, this then checks that the domain is used in the CORS header and if not, the CORS header is not set.

Protect Your App from Too Many Requests

There could be a security issue with the posts_per_page endpoint, particularly If you set your CORS header to allow any domain access to the REST API.

To combat this, you can override any value set for the filter posts_per_page by hooking json_query_var-posts_per_page and limiting to the maximum amount, let’s say ten. To do this, you need to use this code:

add_filter( ‘json_query_var-posts_per_page’, function( $posts_per_page ) {

if ( 10 < intval( $posts_per_page ) ) {

$posts_per_page = 10;


return $posts_per_page;


To change the number of posts, you simply change the value, so if you want five, replace 10 with 5.

Optimisation Time

The REST API uses standard queries to the database. Posts use WP_Query, users WP_User_Query etc. This means that the easiest way to optimise is by using the same methods, for example, as WP_Query leverages object caching, you can use  a persistent object cache like Memcached or Redis to improve performance.

Page caching won’t work as this serves static HTML files to the frontend – no good when you aren’t using frontend HTML. You can create a basic cache for requests for the REST API that uses the WP-TLC-Transients library. It checks for previous requests for the same URL and returns the same response. If it can’t find one, the REST API is allowed to build the response and this is cached before serving, all thanks to the json_pre_dispatch filter.

The json_pre_dispatch filter shows $result and $serve to the filter, with $result defaulted to false. When the filter doesn’t return false, the value is used in response. The $server variable is the JSON server which formats the results properly.

Here is the code for the REST API cache library:

add_filter( ‘json_pre_dispatch’, ‘jp_rest_cache_get’, 10, 2 );

function jp_rest_cache_get( $result, $server ) {

//make sure rebuild callback exists, if not return unmodified.

if ( ! function_exists( ‘jp_rest_cache_rebuild’) ) {

return $result;


//get the request and hash it to make the transient key

$request_uri = $_SERVER[ ‘REQUEST_URI’ ];

$key = md5( $request_uri );

//return cache or build cache

$result = tlc_transient( __FUNCTION__ . $key )

->updates_with( ‘jp_rest_cache_rebuild’, array( $server ) )

->expires_in( 600 )


return $result;


This is just the preparation that you need to power a single page web app using REST API. Once you have this in place, you can start to use REST API to build a single page web app by setting up a node server and then building the front end.

John Hewick

Author John Hewick

John is a full stack developer, with 10 years’ experience building websites with WordPress. Working with Elementary Digital for the last 4 years John has met all the challenges that have been sent his way.

More posts by John Hewick