In this post I will explain how I enabled server side rendering for my blog.
Adding Server Side Rendering
Lately there has been a lot of talk about server side rendering (SSR) in the context of popular Javascript frameworks like Angular and React. The main problems you solve with SSR are better SEO, and performance improvements from rendering pages from already generated static html. This works well for Javascript frameworks, but there is no reason you can’t benefit from the same technique for server side web apps as well. In fact it’s much easier to enable since you don’t have to worry about a handshake between SSR pages and the client side counterpart.
My use case is a blog application where I generate an article on the server using a combination of Node/Express with Mustache templates. Since blog articles rarely change, it seems wasteful to spend server cycles re-generating the same article for every request. Not only is this less scalable, it’s also more expensive since my Azure bill is based on server usage.
Wouldn’t it be better to generate the blog article html once, and keep serving the same html document for every subsequent request?
Obviously you don’t want to maintain 100s of html documents manually, so it’s important to automate the process of generating static pages. I recommend doing this as a build step before deploying the site to your server.
My blog is built using a Bazel pipeline with Docker, so for me it was just a matter of tacking on a new custom step that crawls my site and generates static html files.
This may seem fancy, but it’s nothing more than a bunch of http request and file writes. Each generated page is tagged with a timestamp in the form of an html comment on the page. This is not required, but I do it to keep track of when I last generated the site.
Serving Html
Next I re-wired my Node server to serve the static resources directly rather than going through the trouble of re-generating html on the fly. However, there is still room for improvement. Instead of hitting my Node server for every request I am using a CDN to cache the static files. This means my server sees less traffic, but also, users will be served content from localized CDN instances.
I am using Cloudflare as my CDN, which doesn’t cache html by default, but makes it easy to configure html caching based on url patterns. I currently have set it up to cache all articles. Cached articles will come back with the header cf-cache-status: HIT. Cache misses come back with the same header, but the value is MISS. Reloading a page once or twice is usually all it takes to add a page to the cache.
If you load up one of my articles, like this one, you can inspect the request headers in your browser’s network tools to see the page’s status in the cache.