TAG Panel: Differentiate Your Customer Experience
Join the CX and Product Management Societies to hear from our panel of Human-Centered Design experts on the business value of Agentic AI.
This site uses cookies to enhance your browsing experience and deliver personalized content. By continuing to use this site, you consent to our use of cookies.
COOKIE POLICY
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 rendering, touting benefits of ditching page reloads, much cheaper hosting, and easy and unbridled interactions and animations.
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.
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 browser. This 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.
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:
To a service-oriented, loosely coupled, stack as seen here:
The JAM in Jamstack stands for JavaScript, APIs, and Markup.
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?
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.
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.