Vue.js & the WordPress REST API on a large content site
When we set out to build our first large scale Vue.js website last year, there was hardly any information online to help us gauge whether or not this would work well.
Since then, I’ve seen a few articles and some tutorials on using Vue.js with WordPress and the WordPress REST API, including a few on theme and plugin development. However, what I have not yet seen is an article describing a project of significant size and the underlying architecture supporting it. This is where this piece comes in. It’s not a tutorial, or a guide, it is simply an overview of our experience of actually building something reasonably large on this stack.
UPDATE: I wrote a follow up post on how the Yoast SEO bit works over here:
https://medium.com/nona-web/wordpress-vue-and-nuxt-an-seo-love-story-7593d0827730
So, how big is this project?
- +-3000 unique posts/pages
- 10 post types
- 5 taxonomies
- Thousands of visitors daily
What tech stack did we use?
- WordPress (hosted on Pagely)
- Vue.js (contact me for a full list of supporting NPM packages)
- Nuxt
- AWS (S3, EC2, Elastic Load Balancer, Cloudfront CDN)
- Elasticsearch
- MailChimp (newsletters)
- A custom enquiry API
How do these parts fit together?
We host a WordPress site with Pagely (who, incidentally, host on AWS themselves anyway). The client uses the WordPress CMS to load and edit their content, and media content is offloaded to Amazon’s S3, using the Amazon offload S3 plugin by Delicious Brains. When records are added or edited, the ones which are searchable are also hooked into an Elasticsearch index — more on this later.
The content is exposed using the WordPress REST API, and Vue consumes the REST API, using Nuxt to handle the routing. A Node server is hosted on AWS, on two EC2 instances balanced by ELB sitting behind Cloudfront.
What happens when a user browses the site?
When a user first requests a page by typing a url into a browser (the pink block in the image below)
The request is originally handled by Cloudfront CDN. Cloudfront checks if it has a cached version of the requested URL, and if it does, the cached version is returned to the user. This contains a number of CSS, JS, and other media URLs (these are hosted on S3 behind Cloudfront) which will then be served to the user’s browser.
If Cloudfront does not have a cached version of the page, it requests one from ELB, and ELB in turn requests one from either of the two EC2 instances. The EC2 instances both run identical Node servers (which serve our Vue.js app), and make requests to the WordPress REST API for the content needed for the page.
When a user clicks on an internal link
After the initial load, the website is actually now only JavaScript running in the user’s browser. When an internal link is clicked, the browser requests updated content from the WordPress REST API directly, and Vue.js updates the page and associated metadata (SEO, state variables etc).
When a user submits an enquiry or newsletter registration
The browser sends a request to our “middleware” application — running on a Node server on another EC2 instance. This middleware application sends the request on to the client’s enquiry API, or to MailChimp.
This was a tricky, but necessary step, since MailChimp and the enquiry API would not accept requests directly from a browser (security), and therefore required a connection from a server.
Why did we choose Vue?
The choice came down to either Vue or React. Another team at Nona Creative was keen on React, so we decided to use Vue instead so as to compare the two — it was the up-and-comer and we wanted to know what all the fuss was about.
It appears to have been a reasonable choice.
We’ll be trying React for our next project in order to get a feel for both, and learn which one we prefer through experience, rather than hype.
Which parts of this were difficult to get right?
SEO
- In the past, we’ve relied quite heavily on Yoast’s WordPress SEO plugin, which automatically adds most of what you need for SEO to your website both backend and frontend.
- Doing without that automation was very tricky in the beginning, as we had to pass all the relevant SEO data through to the front-end ourselves, over the API.
- We still use Yoast so that the client can more easily tweak their own SEO data, but we needed to create our own PHP class to handle gathering and sending that data through to the browser.
- Nuxt handles server side rendering so that Google can crawl full html pages without any downside to building the site as a single page application from an SEO perspective.
WordPress as an API for the first time for the whole site
- While this was quite pleasant to work with, it was the first time we’d used it for an entire website, and it took far longer than we’d anticipated to get everything up and running .
- We also tried writing most of the database queries ourselves using SQL, which, in retrospect, probably wasn’t worth the time since the endpoints are cached anyway and the WP queries would have been more familiar.
Deployments and AWS
- This was a whole new world for us — configs stored on S3, and Circle CI deployments to Elastic Load Balancer, test servers etc.
- Circle made our lives a lot easier, and while it feels reasonably simple and familiar now, there was a lot of wiring up to do and the learning curve was steep.
- We also needed to learn a fair amount about caching and uncaching, and made use of Cloudfront’s API and a curl request to the Pagely server to achieve this from the WordPress back-end. This allows for the uncaching of individual pages conveniently through the admin.
Using NUXT for routing
- There was nothing online about using Nuxt, so, for once, we couldn’t rely on Google to answer all of our questions.
- Overall it was pretty simple to use, but the build process takes an unfortunately long time before the version 1.1.1 update.
How did it all workout in the end?
Pretty great!
- We learnt one hell of a lot.
- The website is incredibly speedy, particularly switching between pages.
- Reactivity is awesome! Change a single variable to update areas all over the site — think maps, currencies, prices, telephone numbers, etc.
- Building a site in an API / Client manner is more extensible. The same back-end can be used to provide data to other apps, or sites in future. We’re about to make use of this feature, which is exciting!
- The client is happy, and so are we.
Would I recommend doing this?
Hell yeah! It was a lot of fun and has many benefits, as listed above.
Have you tried building something similar with WordPress and or React/Vue? Tell us about it in the comments below!
UPDATE: I wrote a follow up post on how the Yoast SEO bit works over here:
https://medium.com/nona-web/wordpress-vue-and-nuxt-an-seo-love-story-7593d0827730