Opinions & Insights
JAMstack vs Isomorphic Server Side Rendering
This was a huge benefit when converting our code base from Angular to React last summer. Content can still be generated at build-time and requested on demand through APIs while developing a new application in tandem with the current.
Isomorphic server-side rendering
You probably don’t need SEO
Fetch as Google is a tool to check if Google has found your rendered app. The directions for using this tool are in Google support, but before they will work, you need to sign up to access Google's Search Console. Once you get into Fetch as Google, be sure to use the Fetch and Render button to get a visual indication of whether or not Google is seeing your content.
To better understand this, here is an image:
*Image courtesy of Saturday Morning Breakfast Cereal
Another project worth looking to is Graphcool’s Prep, which provides prerendering that can be setup via the command line and open source as well.
Render at build time, not at runtime
In order to do server-side rendering correctly, you need not just one but two routers, one for the client and one for the server. You also introduce a level complexity when developing your application that’s not needed in most cases. Every time a new route is created on the client, it needs to be mirrored on the server. In addition to all this, you have to have a server running at all times to provide the benefits needed to perform server-side rendering.
Why wait for pages to build on the fly when you can generate them at build time? In recent years, the cost of hosting static files has dropped tremendously trivial to host. When it comes to minimizing the time to first byte, nothing beats pre-built files served over a CDN. You can move server-side processes into microservice APIs which greatly reduces the surface area for attacks. You can also leverage service workers to perform caching and pre-caching data.
The JAMstack ecosystem provides a number of different options via static site generators that render content statically. But if React is needed over everything else, you might also consider the lesser known renderToStaticMarkup. Though this function is not right in all use cases, it is a pretty nice method available in the standard ReactDOMServer and can be called after data is fetched from the API to be rendered at build time. This gives you another way to get a React rendered a static site without the need for server-side rendering.
The Webpack ecosystem provides the Static Site Generator Plugin solution as well to provide a minimal, un-opinionated static site generator directly in your webpack.config. This plugin brings the world of server rendering to your static build process and is the backbone of a few React static generators. You can either provide an array of paths to be rendered, or crawl your site automatically, and a matching set of index.html files will be rendered in your output directory by executing your own custom, webpack-compiled render function. You can read more about this in the project’s README.
Note on Progressive Web Apps (PWA)
Progressive Web Apps will be mentioned a lot after this point in the article. PWAs are a new way to deliver amazing user experiences on the web and based on there PRPL pattern. This is a focus on the minimum time-to-interactivity, maximum caching efficiency, and simplicity of development and deployment.
Are you really gaining those performance benefits server-side rendering is claiming?
Addy Osmani recently tweeted a new version of the TodoMVC, which is the Hacker News clone. You can view some example projects cloning the Hacker News Progressive Web Apps using a number of technologies while getting optimal performance using the PRPL pattern. I thought this was a great idea and decided to build my own to prove a point about JAMstack vs Isomorphic Server-side Rendering.
— Addy Osmani (@addyosmani) May 29, 2017
I did some testing myself and compared 2 server-side rendered Hacker News apps to my client-side only and the results are below. The data is fetched the same way in all cases through the Official Hacker News open API. Now consider that these metrics are from sites built by 3 different people using completely techniques, so your mileage may vary. I just am just trying to see if server-side rendering is actually beneficial. Also, please consider that I am not taking into consideration the time for data fetch from the Hacker News API(~70-80ms), my testing is just focusing on first byte, first connection, and full HTML download. I am not focusing on PWA requirements, though I did include the data since it was nice to look at.
Just for reference, these are the performance numbers for the existing news.ycombinator.com below. I used TestMySite.IO and performance.sucuri.net. These are both great sites for testing how fast your project is delivered to the end user. I also added Google’s Lighthouse, which has a strong emphasis on PWA, not the gold standard yet but interesting to look at.
I am not sure of how Hacker News is built, and for this argument, I can assume they are not using JAMstack but indeed using a CDN.
This is a Hacker News clone using a boilerplate:
It appears that this clone of Hacker News is not performing well outside the US. This is not due to the code itself but actually, the CDN not being global-ready. I am sure switching that will improve the TTFB. I also notice the full download of the HTML is a bit long, most likely due to the initial round trip to the server to fetch the rendered HTML. This is a downside to server-side rendering—a lot of optimization is needed to improve that TTFB. On the contrary this site performs really with the lighthouse performance score, show
PWA Hacker News clone with server-side rendering (site, code): This is a server-side rendered application. I did notice there are a few commits from Addy himself improving on the PWA aspect of the project to make this site PWA compatible.
This page is also clearly on a global CDN and checks all the boxes for performance in regards to the TTFB. There is not much bad to say about this setup, some of the techniques use for caching are pretty cool to look at.
*Disclosure: I mentioned above all the sites were using the same API and this site is not when the service work is caching the content. They are using a clever work around getting past a slow initial connection. You can read up on that here in this merged commit, I plan to study this technique in the near future.
Client-side only Hacker News clone with no server-side rendering (site, code): This is my Hacker News clone. I pulled most of the code from this repo and made very few changes. I am also not taking advantage of any prefetching with service workers, but just relying on Netlify’s CDN and what comes standard from the new create-pwa-app CLI.
Just looking at the numbers, hosting a JAMstack site on a CDN gets you the best time to the first byte even without consideration for isomorphic rendering. As mentioned above I have plans to improve my Google Lighthouse score by including some of the tricks used in the React-HN app above, but for now, I think this performance will suffice.
It is clear that with little effort and leaving out the consideration to server render anything, I was able to get a site that performs better than most just about as good as the best. This is because I have access to a global CDN that serves content much faster when the request is coming from the same place of origin as the server. If you are not familiar with how CDNs work, I highly recommend this post on the Optimizing Your CDN Strategy for the Ever-Changing Online World.
I also noticed, while improving my Lighthouse score for the PWA rating, my performance went up 4 points on that scale just by complying with Best Practices and optimizing attributes.
How are much are you paying to keep that server running?
The biggest benefit to choosing JAMstack over server-side rendering is hands down the cost. I mentioned above that you will not lose out on revenue with missed SEO because there are a number of ways to test that the Googlebots can see your site. But what is the point of saving on SEO cost when you are spending to keep servers running?
When your deployment amounts to a stack of files that can be served anywhere, scaling is a matter of serving those files in more places. CDNs are perfect for this and often include scaling in all of their plans. Most CDNs, including Netlify, can offer this for free or for pennies on the dollar.
Stop paying for seconds used or bandwidth—switch to a model where you can ship without pulling out the abacus.
What if I really need Isomorphism?
There have been a few companies I know, like Pinterest and Eventbrite, who recently made the switch to React and server-side rendering their Python applications. The talks always leave me baffled by the complexity of a task like this, again not something everybody needs, but what if I told you can put isomorphism and JAMstack all in the same cake batter?
I highly recommend Phil Hawksworth’s talk on achieving Easy Isomorphic Rendering on the JAMstack. He breaks downs his needs for maintaining a cost-effective solution with fewer points of failure.
Twitter is a Global company focused on providing the best experience to all users worldwide and which is why 5 years later that released Twitter-lite, a progressive web app with absolutely no server-side rendering. The focus is on time to first interaction and getting the first tweet on the screen as soon as possible no matter how slow the network.
In Nicolas Gallagher’s React Europe talk he mentions that most users of Twitter are repeat visitors and user a PWA enabled browser that leverage the browser cache and does need a running server to deliver content.
Though isomorphic server-side rendering is a popular choice, but it might not be the right choice for you. Be sure you are solving the right problems and getting the best speed, performance, and lowest cost for your site. With the JAMstack you have the chance for all three of those being met. Consider moving towards a PWA to get better results without the need of an always-on server and be sure to consider whether or not you actually need server-side rendering, you might benefit more from the JAM.