Building Decoupled Sites and Apps with GraphQL and Next.js
This article provides an overview of contemporary (in September 2017) sitebuilding with the Next.js JavaScript framework together with Content Management Systems (CMS) that support the GraphQL specification. This includes, but is not limited to, Contentful, Drupal, eZ Platform and WordPress.
Those who are so inclined can also take a look at the presentation slides or the video that this article is based on:
Those who are not can keep on reading…
Introduction to decoupled sitebuilding
Decoupled content management is a term that has been popular for some years now. It means that the public-facing website is built using some technologies that are external to the CMS core capabilities. Instead of using internal APIs to communicate to the database, a decoupled approach uses an external API.
The defacto protocol used to communicate between the front end and the back end is HTTP (Hypertext Transfer Protocol), which is the fundamental protocol powering the world wide web (WWW). It has wide support and with recent improvements in with the HTTP/2 version introduced in 2015 it can still be considered contemporary.
On top of HTTP additional specifications are used to define the communications done between the client and the server. The most common method currently is REST (Representational State Transfer) that is an architectural style which focuses on using the HTTP verbs (GET, POST, PATCH...) to define communications.
A decoupled site front end could be built with a number of technologies, but most commonly the JavaScript language is used. The decoupled JS implementation has traditionally been built using a framework that works inside the client (the browser). But since 2009 and the introduction of Node.js, it is nowadays common to run JavaScript on the server as well.
This article focuses on two technologies to build decoupled sites; GraphQL and Next.js. Both of these tools have gathered enough momentum to have staying power on the market - making them a worthwhile investment for organisations and individual developers.
Introduction to GraphQL
GraphQL is a specification that defines a way on how clients can fetch and modify content on a remote site. It is a specification that is not tied to any specific programming language, system or even a communications protocol. Thought, like REST, today GraphQL is mostly used ontop of HTTP. Unlike RESTful approaches, it uses only the POST method form the HTTP specification.
Another key part in GraphQL is that responses for content are always restored in exactly the same shape. This means that if I only need to display, say the title and the image, of a content item I will only request and receive those two fields. In a standard RESTful API I would receive the content block as well, which in this case would be a waste of bandwidth.
Speaking of bandwidth, GraphQL queries can also nest multiple results into a single HTTP request, removing overhead for the multiple response-request cycles often required when working with RESTful APIs.
GraphQL also features strong typing for excellent API consumer experience because of good tooling and automatic documentation. All of the above adds up to excellent developer ergonomics, and the living proof of this is the number of organisations such as GitHub and Facebook who are using these technologies.
Introduction to Next.js
Next.js is a general purpose web application development framework. It is written in JavaScript, but unlike Angular or Express - it is designed to work in the browser and on the server for the start. This means that you can share the exact same code throughout your application without the overhead of setting up univers routing, Server Side Rendering (SSR) or other boilerplate tasks.
React.js, a very popular JavaScript view library, is used by Next.js to provide the user interface rendering capabilities both on the server and the client. This also enables the framework to render the first view on the server, while then letting the browser take over and start communicating to the server directly, over GraphQL in our case.
The above capability has been available for a number of years, but Next.js is the first case where this has been built to a mature, easy to use and stable package that is cost-effective for developers to build on. Together with GraphQL it opens up a world of decoupled sitebuilding that provides a solid ground for a content driven site with rich API-driven eCommerce functionality from Sylius or other contemporary eCommerce packages.
Advantages of using GraphQL and Next.js
The biggest advantage of using a combination such as GraphQL and Next.js might actually giving site developers a chance at using new technologies. This may not give any technical reward, but does motivate CMS developers and help them gear up for the skills they will need tomorrow.
GraphQL has a very readable structure and is easy to pick up. Given the breadth of the implementations across different frameworks and programming languages. This means that the GraphQL specification is likely to be more universally applicable than deep knowledge of any single REST API.
As for React as a view layer, it is a definite bonus. As opposed to templating languages that have no information on the structure of the output, the component structure enforced by React. In addition Next.js supports exporting static assets for the dynamic items.
What static exports means is that even though Next.js runs on a Node.js server, you can export a static package that gets served from a vanilla HTTP server. This in turn translates to high performance, high security as well as lower cost of hosting due to minimal resource use.
Another advantage of this combination is the flexibility of the Next.js framework. As opposed to forcing it's own components for everything, developers can use popular Node.js frameworks like Express or Koa together with Next.js for their backend functionality.
Building from small functional components is inline with the philosophy of NPM and JavaScript in general. Best of all, this is all optional and most developers probably will not be swapping out the router or other components.
Using Next.js does not take out any options from the rich ecosystem that has grown around React.js, which means that developers can use any components and other libraries to expand their application beyond a content driven site discussed in this article.
Adding Redux, MobX State Tree or other state management solutions can also benefit developers to create complex form wizards and other common functionalities used on content driven web applications and sites. Also, it is essential to stress that the GraphQL protocol itself is not limited to transfering content related, but is a general purpose communications protocol.
Disadvantages of using GraphQL and Next.js
For site development the first question has to be that what advantages, if any, does a technical solution provide? In the case of a purely content driven site marketing, a site built with this stack does not necessarily offer any advantage. You need to justify the use of this added complexity.
In fact, because the client will send more information such as the JavaScript library and more to the client, the performance can be worse than than a traditional server driven content delivery method. Together with HTTP/2 and ever increasing JavaScript performance in browsers this concern is deteriorating, but will never be completely gone.
Also, while the technologies of JavaScript, NPM, React, JSX, etc. are familiar to many developers - they are still new to a vast majority of developers building sites with content management systems like WordPress or Drupal. This means that even though Next.js considerably lowers the initial barrier of entry, it does not mean it is trivial to pick all of these in a single go.
Content Management Systems in general handle a lot more than just entry and delivery of content. Layout management, form management and even content analytics are often thought of being in the domain of a CMS. None of this built in utility will be available when building a decoupled site with any technology, so you need to take this into consideration when estimating the functionality and workload of a project built with a decoupled approach.
Due to the nature of Next.js, the development will also have some own peculiarities. Developers will need to keep in mind that the JavaScript they write will need to perform both on the server, sometimes leading to hard-to-find bugs and issues with caching unheard of in more traditional implementations.
In regards to performance if you are not doing caching on the server side rendered, you will create a CPU bound workload on the server. Even though the V8 engine running Node.js has world-class performance characteristics, and React 16 also improved SSR performance, the fact is that they can never compete with sending over a blob of HTML.
You can set up a CDN or a reverse proxy in front of your Next.js server to cache the server side rendered HTML, but this can lead to more trouble as the client expects the HTML to match whatever the API is output. So purging caches is something that you'll need to have a strategy for, especially if you will run an installation with hundreds of thousands of individual URLs.
For security Next.js, and especially exported static HTML, add no added security implications. But for GraphQL the case is something else. While GraphQL has no major security flaws in it's architecture, the chain is only as strong as it's weakest link. The developers creating the GraphQL backends can take some shortcuts that will cause the GraphQL backend to either leak sensitive information.
Alternatively crafted GraphQL queries can allow the to be overloaded by complex queries that put the server on it's knees. This in turn will slow down or completely disable the API and bringing all the traffic to a halt where you are performing SSR with Next.js on A Node.js server on the fly.
While SQL is not comparable to GraphQL, it is still also worth considering that any input you are sending to your GraphQL backend is not to be trusted. Especially since with the introspection of GraphQL, malicious attackers can get a full view of the capabilities of your GraphQL endpoint. This is why it would be essential provide only the minimal capability to a public GraphQL endpoint.
Conclusion
The combination of the GraphQL protocol for communications and Next.js for application development with React.js for templating is a mature option that provides a valid option for building websites. Certainly for sites that rely heavily on added value features from the CMS, should likely look at more traditional approaches at this point.
For the developers this stack has a low barrier to entry, but all in all the approach might not provide any real benefits over a server side rendered HTML blob. On the other hand if you do want to provide more rich functionality on the front end, the use of Next.js will give you a significan headstart with a unified architecture for your application.
I look forward to seeing where the market evolves, as there are obviously a number of competing technologies available. And I'm sure there's plenty more that we will see around this topic. One of the most interesting of which is Gatsby, a site generator that adopts GraphQL as an internal API, which could be a better option for purely content driven sites.
-- Jani Tarvainen, 28/09/2017