Our story begins in the early 2000s. JavaScript, less than 10 years old, was an unimposing new kid on the block, mostly seen as a relatively limited scripting language for web page manipulation. However, as different browsers competed to run client-side scripting with greater speed and performance, their capabilities grew, and so-called “Web 2.0” applications emerged – marked by their interactivity, user-focus, and ease of use (think Facebook, YouTube, Gmail, Flickr). These phenomena were powered by JavaScript (at least in part) and earned the language more respect through the aughts, leading to the eventual shedding of its reputation as a rinky-dink browser scripting tool.  

It was in this climate in 2009 that the NodeJS was born – it was certainly not the first server-side JavaScript runtime, but likely the most powerful, and, most importantly, the one with the best timing. Over the next few years, it saw massive adoption among API developers even in enterprise environments and has recently been afforded such accolades as the “Gold Standard” for web app backends. This will be important later.  

From 2010-2014, fueled by ever-more-powerful browsers and increasing demand for rich applications, client-centric JavaScript libraries and frameworks exploded onto the scene – among them Angular, Ember, Backbone, React, and Vue. Client-side Rendering (CSR)-based Single Page Applications (SPAs) entered vogue status, and there were plenty that claimed victory over more traditional server-side renderingtouting benefits of ditching page reloads, much cheaper hosting, and easy and unbridled interactions and animations.  

The SSR Comeback 

In the mid-2010s, a few key drawbacks of client-side rendering became apparent to the web development community. These downsides fall under two main categories: performance and marketing. 

Performance 

  • SPAs, which need to download and run a bundle of JS before rendering, suffer from a slow First Meaningful Paint. This can have a direct impact on eCommerce conversion rates, or more drastically, cause users to abandon the application entirely. 
  • If you have a network intensive application, the user experience can be hurt by a slow network connection (as opposed to keeping heavy-duty network activity on a server you control). 

Marketing

  • Increasing traffic through search engines (Search Engine Optimization, or SEO) relies on having informative and indexable pages that crawlers can parse. SPAs typically have barebones HTML document that in turn links to all the JS it needs in order to work, making them less search engine friendly. Caveat – Google (and presumably other browsers) can render and understand web pages, even SPAs. However, if SEO is a priority, having pre-rendered pages is the safe bet.  
  • Sharing thumbnails, snippets, and previews on social media is much easier with pre-rendered pages than it is with a dynamic SPA.  

So, in the later teens, server-side rendering started to see more adoption, and a higher order of frameworks emerged that enabled and accommodated server-side rendering – notably Next.js (React) and Nuxt.js (Vue). These are excellent frameworks that offer out-of-the-box support for SSR, along with other intelligent defaults that reduce developer decision-making and offer anti-pattern guardrails – altogether giving more time to developers to focus on the application itself. Honorable mention goes to Angular Universal, which makes it very easy to tack SSR support onto existing Angular SPAs.  

What is the common denominator to all three of these frameworks that makes SSR so accessible? Universal JavaScript. 

Universal (or Isomorphic) JavaScript, is simply code that can be run on both the server and the browser. Remember NodeJS from earlier? Well, it turns out the same code used to render applications in the browser can be used to render applications in a server runtime (like Node). Under the hood, that is what all three of the above frameworks are doing – they are, at some level, running the same code on both the server and the browserThis pattern grants developers access to the benefits of SSR without them having to tangle with different languages and code between the server and the client (looking at you, PHP)Universal JavaScript-based applications can therefore enjoy the performance and marketing related benefits of SSR and dynamic and rich client-side interactions.  

Enter the Jamstack 

Since around 2017, a piercing question has been making its way into more and more architectural discussions: 

What if you don’t need a web server at all?  

That is, what if you could pre-render the entire website and serve the same static files to everyone, and rely on the browser as its own sort of “runtime” to run all the dynamic JavaScript you need to hydrate and enrich the app? The answer is that the solution would likely be cheaper, more secure, and more scalable, all of which are intrinsic benefits of using CDNs to serve static content.  The follow up question is, where does all the business logic from the web server, app-server, and database go, if we remove the entire server-side runtime?  

The answer to this is a paradigm shift from a vertical, monolithic stack as shown in this diagram: 

traditional web

To a service-oriented, loosely coupled, stack as seen here: 

JAMstack

The JAM in Jamstack stands for JavaScript, APIs, and Markup.

  • Need rich client-side interactions, with user-specific experiences and oft-changing data? Client-side JavaScript is your friend, along with increasingly powerful browsers to run it.
  • Need business logic for things like authentication or eCommerce? Forget the monolithic web/app servers, and say hello to modular, loosely coupled APIs.
  • Use markup (or markdown!) and templating in conjunction with non-interactive, infrequently updated content from a headless CMS to statically generate as much of your website as possible at the build phase.

And voila! You have a snappy, pre-rendered application, enriched by JS at runtime, that is intrinsically scalable, secure, and cheap, with the added bonus of separating your concerns. Front-end development, API development, and content management are each an art and science unto themselves, and the natural separation of the Jamstack allows for more focused cultivation of expertise in each.  

That all sounds great, but so does going on a two-week meditation retreat to restructure your character. What matters is the practicality. So, what are some practical considerations to keep in mind regarding the Jamstack 

  • Greater reliance on external services – Bnature, you will be imparting control and logic to decentralized services, each of which is liable to be a single point of failure. It can be a scary proposition to put your faith in a service’s reliability, availability, and data stewardship, especially services that are black-box or offered by third parties. (This is reminiscent of Ken Thompson’s reflections on trust.)  
  • Entire site must be pre-built on each change – Currently, static sites must be fully generated upon each change, which can lead to change backlogs and lots of waiting on builds, particularly for larger sites. This was well-detailed in Smashing Magazine’s case study of its own transition from WordPress to the Jamstack. However, with Gatsby’s recent release of incremental builds (and other implementations sure to follow), this consideration will be outdated soon 
  • May require an institutional paradigm shift – The Jamstack is not easy to adopt incrementally due to its reliance on an entirely different architecture. Because of this, moving from a traditional architecture to the Jamstack in an effective way may require resolute initiative and some degree of institutional willingness to venture into new territory.  

All said, it’s difficult to deny the compelling reasoning behind the Jamstack, and it would be a lie to say the movement wasn’t growing, as evidenced (loosely) by the literally hundreds of static site generators that have sprung up in the last few years; generators that are well-used and continually maintained. And, while there has been a perception that Jamstack is really only suited for static, content-oriented sites, its broadening portfolio of powerful applications serves as evidence that static does not necessarily mean unmoving. 

The Takeaway 

Even if you don’t go gung-ho on the Jamstack, there is a moral that’s easier to adopt: do as much work as possible at build time to take the load off at runtime. Does the text of a blog post need to be fetched upon every request? Does the unchanging “About” section of a website need to be rendered on demand? When building out a new application, make it a practice to ask, “Does this need to be rendered at runtime?” If the answer is no, then there is likely an opportunity for optimization.  

Note: Next.js and Nuxt.js, the two powerful SSR frameworks mentioned earlier, both offer SSG out of the box. Next.js goes a step further with its automatic static optimization, detecting and pre-rendering everything it possibly can at build time, unless explicitly directed otherwise. Frameworks of this kind, that offer functionality across the entire SPA – SSR – SSG gradient with a bias toward SSG, are wonderful at both giving developers options and beating the drum for the static movement.  

You May Also Like These Topics