Introduction
Introduction to the JAMstack

Introduction to the JAMstack

This article aims is to introduce the JAMstack - what is it about, what benefits are there for those who use it and just an overall view of some of the services that can be used under the umbrella of the stack.

If you're interested in a condensed version of this article, have a look this video of my talk "Unleash the Power of the JAMstack" delivered at Front Conference.

Tamas Piros - Unleash the Power of the JAM Stack from Front Conference Zurich on Vimeo.

🚨 If you'd like to deep-dive into the JAMstack, please check out https://jamstack.training - a training portal dedicated to the JAMstack.

What is the JAMstack?

Simply put the JAMstack is short for JavaScript, API and Markup, however, there's a lot more to the stack than what the abbreviation suggests.

A quick Google search reveals that there are a lot of definitions out there, but the one I really like is a quote from Phil Hawksworth (Netlify) who said the following about the JAMstack:

A modern architecture: Create fast, secure sites and dynamic apps with JavaScript, APIs and pre-rendered Markup, served without web servers.

This quote is jam-packed (excuse the pun) with a lot of remarkable points such as 'fast', 'secure', 'dynamic' and 'pre-rendered'. The most intriguing fact from the above statement is that a JAMstack site is 'served without a webserver'. How is that even possible I hear you ask. What if, we could rewrite this quote and say that "a JAMstack site is served without an 'origin server'". This would be a bit more meaningful because one of the key differentiators of the JAMstack is that there's no origin server, sites are served from an edge server.

Origin Server vs Edge Server

An origin server is just a computer (a server) that has an application running on it (typically a web server such as Apache), and its purpose is to respond to requests arriving from clients (i.e. the browser).

Think about the LAMP stack: in this setup, we have a server running Linux, with an Apache webserver. We also typically have some database (such as MySQL), and we use a server-side programming language such as PHP to generate some content, which is transformed to HTML. Whenever we request a page from the browser, a PHP script gets executed, that script potentially runs a query to collect data, PHP takes that data and renders an HTML structure which is then displayed in the browser.

There are two key things to remember here: First is that this process happens on each request, and second is that we have some code that is being executed on the server.

The scope of this article doesn't allow us to investigate things like scaling, maintenance and security of such an architecture (What happens if 100k users are now visiting my site? What security considerations we need to think about to prevent malicious code execution? What if now the application server is separated from the database server?) but experienced developers are familiar with all the pain points.

A quick side note here regarding the MEAN/MERN stack. This stack also has an origin server because we have Node.js running, along with Express (which acts as a webserver) so we still have server-side code execution). One of the key differences here is that now the browser has become the main execution engine.

How is an Edge Server Different?

An edge server typically refers to a set of computers that are distributed globally with the sole purpose of delivering content as fast as possible to the closest requesting user.

Think about a CDN (Content Delivery Network). We use those today to deliver static assets such as JavaScript and CSS for a number of reasons: CDNs are very good at caching static assets; they always serve them to the closest requesting user - meaning that a user in Singapore would receive a JS or CSS served from a CDN in Singapore, while a user in Spain would see the assets served from a CDN somewhere Spain.

CDNs also take care of load balancing, automatic scaling, and they also do redirection of traffic under heavy loads. All of this is out of the box, automatically configured. As developers, we never need to worry about this.

Now, here's a crazy idea. If we store static assets like CSS and JavaScript already on CDN edge servers, why can't we store HTML there as well? HTML, in essence, is really just a static, markup language. But how would that work? How could we have data and static structure available when people are requesting a page? Enter pre-rendering.

Pre-rendered Markup

To have static HTML assets - which we could place on a CDN - we need to generate the markup somehow. There are multiple tools out there that allow us to do this - these are referred to as Static Site Generators (or SSG for short).

The key difference is that SSGs generate HTML ahead-of-time, or at build time and not at request time. This means that all the data that HTML pages require are collected at build time and the result is going to be valid, static HTML markup that could be placed on a CDN or to any static site provider.

There are a significant number of SSGs out there today, some are leveraging popular frontend frameworks such as React and Vue, some use vanilla JavaScript, and some are based on other programming languages such as Ruby or Go.

At this point you may be confused. JAMstack is JavaScript, API and Markup, so how does Ruby and Go come to the picture? It's important to understand that generating (pre-rendering) static HTML is the job of a tool, running on the server-side. Therefore we can leverage any programming language to generate HTML for us. This is related to the pre-rendering part. The JavaScript bit in the JAMstack refers to progressive application enhancement - I can use client-side JavaScript to call APIs in my application. These two things are not to be confused.

Example Static Site Generators

Name Language URL
Gatsby JavaScript (React) https://gatsbyjs.org
Nuxt JavaScript (Vue) https://nuxtjs.org
Next JavaScript (React) https://nextjs.org
VuePress JavaScript (Vue) https://vuepress.vuejs.org
Gridsome JavaScript (Vue) https://gridsome.org
11ty JavaScript https://11ty.io
Jekyll Ruby https://jekyllrb.com
Hugo Go https://gohugo.io

Please note that there are a lot of other Static Site Generators out there, for a more extensive list, check out https://staticgen.com

Static != Static

So far, we have discussed that we can generate static HTML at build time. However, these HTML pages are not static, in a sense that we can leverage APIs to make our HTML dynamic and interactive. In fact, the A in the JAMstack refers exactly to this.

So what kind of APIs can be used? The answer is "any". Literally.

First and foremost, we can utilise a custom-built REST API. You may be in a situation where your work at a company that exposes some API. It's straightforward to consume that API in your website and consume that data, at build-time to build the final HTML.

There's another type of API usage that I'd like to draw your attention to. Thinking along the lines of progressive enhancements, in the "static" pre-rendered HTML, we can very easily use some client-side JavaScript and leverage the Fetch API to make a request to any API and append the result to our HTML.

Standing on the Shoulders of Giants

We can also leverage an API from a third-party service provider.

The key thing to understand here is that there are a lot of companies out there that offer great services and they usually expose an API or have various SDKs to be used with their service. These organisations are experts in their domain - they usually do one thing, and they do it well. Thinking about accepting payments on your site? Use Stripe or PayPal. Do you want to serve, optimise and transform images? Use Cloudinary. Do you want to implement authentication? Use Auth0. The list of service providers is really endless and using the old Apple analogy of "there's an App for that" it's safe to state that "there's an API for that".

And the beauty of this? Apart from the fact that these service providers are true experts, they also take care of all the infrastructure - they maintain it, they manage it, and we don't need to worry about it at all. All we need to do is make a call to an API.

But I Want to Execute Server-Side Code

Should there be a need for further customisation - or maybe a way to execute server-side code (remember, this is not possible on an Edge Server) or even to bridge two APIs, Functions As A Service can be leveraged along with Serverless computing.

In a nutshell, with Functions as a Service, we typically write and deploy a function to a third-party provider (like AWS), and we get an access URL to that function. Calling that URL will invoke the function (server-side, at AWS) and return us the result.

If you'd like to learn more about FaaS and Serverless, please read the article titled Introduction to Serverless

Content (Headless CMS)

Every web app that we create is driven by content. Let's discuss where content and data could be coming from in the JAMstack. Where would a static site get its data? The answer is headless CMS. A traditional CMS (such as Wordpress) couples the content/data layer with the presentation layer. This is referred to as a monolith application.

A headless CMS, on the other hand, separates/decouples the presentation layer from the data layer. In other words, a headless CMS doesn't care about how the data is presented, but it allows us to store and manage the content.

Note that some headless CMS out there provide users with a UI to manage the data. This is not to be confused with the presentation of the data - that's still not controlled.

We differentiate two types of headless CMS: API and Git-based. Each of them has different use-cases. An API based headless CMS allows us to store data in a database (SQL or NoSQL) and enables us to access that data by exposing RESTful API endpoints. Git-based headless CMS store data (typically Markdown files with YAML frontmatter metadata) in Git (GitHub, GitLab or BitBucket).

Example Headless CMS

Name Git/API URL
Strapi API https://strapi.io
Netlify CMS Git https://netlifycms.org
Contentful API https://contentful.com
Cosmic JS API https://cosmicjs.com
Appernetic Git https://appernetic.io

Please note that the above is just a short list of available headless CMS. For a much more extensive list, please visit http://headlesscms.org.

Benefits

We talked about the essential components of the JAMstack and now let's shift gears and discuss why someone would decide to use this stack. Certain elements in the JAMstack benefit the end-users and others help the developers and organisations going down the JAMstack route.

Let's discuss the end-user perspective first.

End-users

How do end-users benefit from the JAMstack? By having a much better experience with a site that is using this stack under the hood. One of the most important things is the performance, which is not only produced by techniques applied by developers such as Static Site Generation and Server Side Rendering but by way of using CDN Edge servers.

The site that gets delivered to the users only contain HTML, CSS and JavaScript - there's no server-side code execution to wait for, no database queries to run and the site, is, by default distributed globally and is returned from the closest edge server to the requesting user.

Because of the decoupled nature of the applications created via the JAMstack, users also benefit from faster, leaner deploy cycles - they can have access to newer features much faster.

Developers

Developers (and businesses) benefit from using the JAMstack for multiple reasons.

First of all, there are specific cost-saving opportunities. Thinking "static first" means that there's no need to have physical servers or provision servers in the cloud making not only the infrastructure more straightforward but an entire project more cost-effective. When we discuss cost, we can't go on without mentioning another type of cost - that is the developers time. Some organisations have dedicated staff for managing and maintaining entire infrastructures - provisioning, development and others. Some other organisations rely on the knowledge of engineers who develop the code and make it their task to manage their own "playground". This has a significant impact on projects because now engineers are spending time on deployment, patches, database installs and other tasks that are distracting them (both time and effort-wise) from their original goal which is to create a site or a web application.

Using services such as Netlify, it's also possible to do atomic deploys - deploy parts of the application and, what's even better, revert any changes through a mouse click. It's an effortless operation and makes site deployment super easy.

Another benefit is that developers can use their familiar environments - the entire codebase lives in Git and now event the content can live in Git and be managed by Git. The whole deployment of a project can also be tied to git pushes and commits.

And we can't let the security considerations go unmentioned. In a traditional stack such as the LAMP or MEAN stacks, there's an origin server that executes code. Potentially there are application and database servers that also communicate with one another. This leaves a vast attack surface area - a potential hacker has multiple ways to attack such a system because there are a lot of moving parts. With the JAMstack, we only have an origin server - no server-side code execution, less moving parts. Plus CDN providers take care of all the security considerations that we may not have thought about.

Conclusion

In this article, we covered the fundamentals of the JAMstack, and I can only hope that the article gives you a good overview. Remember, the JAMstack is not only important for developers because of features such as git workflows and continuous deployment and integration, atomic deploys but also to end-users due to performance reasons.

Author

Tamas Piros

Developer Evangelist, experienced Technical Trainer and Google Developer Expert in Web Technologies. Active conference speaker, passionate about the latest & greatest advancements in web technologies.

View Comments
Previous Post

Using React Hooks with GraphQL