Building an Isomorphic Webapp
I’ve always lived by the “Separation of Concern” principle when it comes to software design. Recently, I’ve came to love a new design pattern for web apps called the isomorphic web app that sacrifices some of the simplicity of a SPA with a backend API for a significant boost in performance.
For web development, the Single Page Application (SPA) that talks to a server API was once the gold standard as it provides the most clear division of responsibilities between the server app and client app. The server serves the data (usually JSON) to the client app to render the web page in the browser. What could go wrong with this approach? Performance.
We are all familiar with the features of a SPA: quick response to user input, highly interactive webpages (think google docs), and ability to use it offline once the page loads. Most importantly for a startup founder such as myself who’s trying to quickly create a prototype of a website with some dummy data, a SPA lets you build a website independently from a server application. In many cases, you can get away with not building a server application at all if you used a sophisticated front end library like React, Amazon S3 for hosting, and data you store in a CSV file. That’s exactly what I did for LooseLeaf.
This separation of concerns improves productivity initially when you are prototyping a MVP for your website, but there’s a point of diminishing returns for a website deployed as a SPA that talks to a server with an API for data. The main disadvantages of this approach are:
Long load time (bad UX)
because the website is bootstrapped, it takes some time for the page content to display itself after the initial load. Initial load occurs when you type the example.com into your browser and press enter. Whatever the browser gets back from the initial load is whatever the server sends.
Bad SEO (bad for business)
Search engines and social sharing are two of the most important means of acquiring new users.
The same thing happens with social media sites like Facebook and Twitter sharing who have their own army of crawlers to render a preview of the page based on meta tags in the header of HTML. The header is rendered on the server side and don’t change when the content changes based on dynamic loading when the webpage is bootstrapped in the browser. This means if you have a website that sells books and a SPA that uses the same template HTML to render different pages for different books, then when you share a link to the page for a particular book on Facebook, the preview will display a generic preview about your website which says something like it’s a place which sells thousands of titles, but will not display any unique information for the particular book. This article did a good job laying out the limitation of a SPA in its ability to generate unique header for social sharing and how to use server rendering to solve that.
What about Pure Server Rendering Solutions?
If you are reading this, that means I’ve convinced you that a simple SPA is not the way to go. A pure server side application is not the way to go either because from a development standpoint, we want to be able to build our client application and server application separately. From a user experience standpoint, once a SPA is fully loaded, user experience may greatly exceed that of a server-rendered webpage. Also I don’t want the entire page to reload every time I click a button.
So the shortcoming of a pure SPA is in the initial load. The shortcoming of the pure server rendering solution is with what happens after the initial load. What can we do to get the best of both worlds? 🤔
Isomorphic Web App Starter Project
I like to think of an isomorphic web app as SPA 2.0. It’s SPA with server side rendering. An isomorphic web app gives you the best of both server side rendering and single page application (SPA). There have been many articles written about the benefits of an isomorphic web app, like this, this, this, and this. There’s a book being written about it. However, not that many tutorials, guides or starter projects to help you get started building an isomorphic app.
Through reading dozens of articles, tutorials, books, and undergoing trial and error, I managed to set up an isomorphic web app that uses the latest stack in the Node and React ecosystem. This include React Router v4, Webpack 4, and Babel.
All the code is contained in this repository: https://github.com/xiaoyunyang/isomorphic-router-demo
To get the code up and running on localhost:3000, simply do:
$ git clone https://github.com/xiaoyunyang/isomorphic-router-demo.git
$ cd isomorphic-router-demo
$ npm install
$ npm start
Here’s a preview for what it looks like:
Client side rendering and server side rendering complement each other. We can build an isomorphic web app that enhances the capability of a server rendered page with a SPA. As articulated in Lullabot’s article, there’s a considerable learning curve when building an isomorphic application for the first time, but like anything with a steep learning curve, there’s nothing you can’t figure out with a bit of googling, experimentation, and leveraging tutorials and sample projects.