SSR a "Create React App" the hard way

I’ve been building out a web app using Create React App, developing and deploying is a breeze. But now I need a server side rendering solution for my specific sitation. All the solutions around the web I have found are great, but they don’t address the issue I have. So in this post I’ll share my own “from scratch” solution. The problem I am solving is:

Google has trouble with my single page app written in javascript, I want to create a static HTML render of all pages inside my app. I want to serve these static pages to googlebot (and other crawlers). Since my app displays a lot of dynamic information (pulled in from an API, updated hourly) I want to be able to easily rerender the complete UI with minimal effort (and compilation steps).

So this is NOT a SSR solution that prerenders an initial page for a user, instead it statically “compiles” a large number of pages in my app whenever the API data changes into plain HTML files which are served through a webserver (to crawlers, not to users). I’ve build my solution for the create-react-app version I am using, which is react-scripts 2.0.3 and uses react 16.4.1. If you are using another version everything below might not work.

Note that my approach is NOT recommended, it requires you to put monkey patch components in your app and forces you to break promises (out of spec compliance). As soon as React updates their lifecycle hooks (again) you will need to come and fix this or you might break everything below. Here by dragons.


Hoganizer: Precompile mustache templates for the frontend

Normally when I start working on a new webapp I end up using Jade as a template language, to get the templates working on the frontend I use a wonderful tool called templatizer which pre compiles all jade templates into plain javascript functions. I love this workflow because it has some awesome advantages like:

  • Insanely fast rendering, because you are just running vanillaJS functions with strings in them.
  • You still get to write your templates in a very friendly format: a .jade file for each template.
  • The compiled templates are stored in .js files, which means you have a lot of control over the client side caching.
  • The whole template parsing engine doesn’t need to go over the wire, this way your total JS size goes down.

But this time I started a new project and we decided to go for mustache instead of jade. After some searching I came across Twitter’s fast implementation of the mustache spec: hogan.js. The library not only promises to be very fast, but also that it consists of different modules that would make it easy to pre compile templates on the server.

There already were some wrappers available, but none fit quite right into my workflow: it must be easy to hook into my buildscript & must have some way of supporting client side development.

Meet Hoganizer, a small wrapper around the Hogan compiler to make this easier.