How to Build Fast and Secure Websites With the JAMstack

How to Build Fast and Secure Websites With the JAMstack
jamstack

The JAMstack has seen a fantastic rate of acceptance over the past few months, and myriad tools and services can now be used to create fast and dynamic web applications. The JAMstack advocates atomic deploys, which yields more frequent, easier deploy cycles, meaning the latest updates are delivered to users in a simple way. 

This has changed the entire development workflow. Traditionally complex applications and features such as authentication, checkout, payment systems, and media management can now be added by a few lines of code. Furthermore, with the JAMstack we no longer use monolith applications, but instead develop smaller components and atomicly deploy them to a global CDN (edge servers). Developers can leverage static site generators, and enhance their site using client-side JavaScript and myriad APIs, which means that they only need to focus on one thing: development. There’s no need to deal with DevOps related tasks.

In this article, we'll review why you should care about this new stack and how to best use it to build faster, more secure websites. You can also watch the talk I gave on this topic at Front Conference in Zurich below.

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

What is the JAMstack?

jamstack: homepage
The JAMstack homepage.

The JAM part of JAMstack is an acronym of the three core concepts that are the heart of the stack: JavaScript, APIs, and Markup. But we need to dig a little bit deeper to find out what the JAMstack is capable of, and how we can use these technologies together to enable great experiences.

A better, albeit longer, description of the JAMstack is that it allows us to create performant websites using easily accessible services and deploy them faster, without the need for an origin server.

The last part of the description is curious. How come there's no origin server?

An origin server is a server that has an application running on it—typically a web server such as Apache or Express—that is capable of accepting requests and providing a response.

The key takeaway from this is that when you think about a classic setup like the LAMP stack, generating a page happens at request time: a user clicks on a link, a PHP file gets loaded, that file may make a request to a database by way of an SQL query, it gathers data and returns some template which is then rendered as HTML, and that's what the user sees as the end product. This process happens whenever the same page gets loaded, although there are some caching mechanisms available, which means that querying for the data may not need to happen every time. However, the concept is still there: we have server-side code to execute on each request.

"In other words, we pre-render the markup, so that when a user requests a page, there's no need to do server-side code execution at all."

With the JAMstack, our approach is slightly different. What if we generate the HTML files based on templating logic and structure, ahead of time—at build-time? In other words, we pre-render the markup, so that when a user requests a page, there's no need to do server-side code execution at all. The resulting HTML code can be placed to any hosting provider's server, to GitHub Pages, or even just to Amazon's S3, and be served immediately.

jamstack: flow chart
JAMstack sites are built with JavaScript, APIs, and markup, and are served without an origin server.
Template Icon

Pre-rendering with static site generators

To achieve what we discussed earlier, we need a tool that is capable of pre-rendering markup. Static site generators (SSG) are designed for precisely this purpose. There are a few static site generators out there today, most of which are based on popular JavaScript frontend frameworks such as React (Gatsby, Next.js) and Vue (Nuxt.js, Gridsome). There are also a few that are non-JavaScript based, such as Jekyll (Ruby) and Hugo (Go aka Golang), or ones that are based on vanilla JavaScript (11y).

"How we pre-render the markup is agnostic to what programming language we use for the tool doing the job."

At this point, you may be wondering why the 'J' in the JAMstack is for JavaScript, when we are talking about Ruby and Go for SSGs. This is, in fact, a question that comes up during most of my talks and workshops. The critical difference is that the static site generators are related to the 'M' in the JAMstack—the markup. How we pre-render the markup is agnostic to what programming language we use for the tool doing the job. The 'J' (JavaScript) bit refers to the fact that we can enhance the application using various JavaScript functionalities, but that's 'client-side' within our app.

This leads me to the second letter in the JAM—APIs.

You might also like: An Insider's Look at the Technology That Powers Shopify.

APIs

You’ve probably heard the expression "standing on the shoulders of giants" before. I find this quote to be very relevant here. Let me give you two examples. 

Traditionally speaking (think the LAMP stack), creating a contact form was somewhat challenging. We had to create a form using HTML and JavaScript, and we had to send the data from the form to a backend (PHP) for processing. The server not only had to process the data, but also had to have a mail server configured and running, so that an email could be sent with the data processed from the front end. This required Unix knowledge, amongst other programming skills.

Another example is authentication. Authentication is typically hard: we need to store the username/password combinations in a database, make sure it's secured, generate cookies and tokens, validate them, and so on. But what happens when the database load triples? What if we never had a separate auth database? How do we scale these separately?

Today, there are a lot of services out there that help us create contact forms and authentication more easily. Formspree is one example for contact forms. All we need is to add an action attribute to our form that points to https://formspree.io/my@email.com, and that's it.

jamstack: formspree homepage
Formspree makes it easy to add contact forms.

In the same way, we can use a service such as Netlify Identity or Auth0 to add authentication to our application.

The point of all this? There are companies out there that are experts in their domain. Formspree only deals with forms and form integrations, Auth0 only deals with authentication, Cloudinary only deals with image management, and Shopify deals with ecommerce and related items. These companies (and others) do one thing, and they do it well. We, as developers, should leverage their services. Almost exclusively, these organizations expose an API or provide us with an SDK of some sort that can be very easily integrated with our code.

"These companies (and others) do one thing, and they do it well. We, as developers, should leverage their services."

When it comes to creating more complex applications, such as an ecommerce site, the problem used to be that the entire application was a large, coupled monolith. The admin interface was tied to the main application, along with the cart, the payment system, the product listings, and the reviews. Everything was under one roof, and it was very difficult to manage small changes. With the JAMstack, we can break the monolith! 

With services such as Shopify and their APIs, we can build a decoupled ecommerce platform and statically generate all the pages for better performance. This means that when a user looks at a product listing, we don’t need to make a database query to gather the data about the product—it’s already done for us, at build-time. 

Changes to applications using this approach are a lot easier to implement, because in order to change something in the product listing, we don’t need to bring down the entire site. Instead, we can make the change, regenerate the pages, and everything gets published to the CDN for us (provided that we are using a service such as Netlify).

jamstack: netlify homepage
The Netlify homepage.

Shopify provides developers with a REST API as well as a GraphQL API to manage the admin side of the ecommerce platform, again completely decoupled from the rest of the application. Let them worry about scaling, load balancing, security, and other things that typically wouldn't be our job anyway.

But what if we still need to execute server-side code? We can leverage Functions as a Service (Serverless Functions), such as AWS Lambda, or Google Cloud Functions. These are typically written in JavaScript and can be deployed on the vendors' servers. All we get at the end of the day is an endpoint, which we can call from our client-side JavaScript code, and which in turn invokes our function and returns a result.

There's also an organization called Serverless, Inc, creators of the Serverless Framework, which encapsulates all these other services and allows us to deploy to any provider using a CLI tool.

You might also like: Deconstructing the Monolith: Designing Software that Maximizes Developer Productivity.

Headless CMS

Usually, a website requires data as well. Think about something like a blog or an ecommerce platform. If we don't have the option to make database queries because we are not rendering our site at request time, how can we make sure that there's still data available? 

Please meet the headless CMS. Now, the name is curious. What's a headless CMS? Think about a classic content management system like WordPress. WordPress is a monolith application where the front end and backend are tightly coupled. There's no way to separate them.

On the other hand, a headless CMS separates the data layer from the presentation layer—in other words, the data is managed in one place, but the headless CMS doesn't care how that data is presented and where it's presented. 

Note that some headless CMS providers do come with a UI, but that's only the admin interface with which the underlying data can be managed—it's still not going to affect how the data is presented to the user.

There are two types of headless CMS out there: git-based and API-based. API-based ones allow us to store the data in a database (either SQL or NoSQL), and expose an API endpoint which is consumable via HTTP calls. The git-based ones manage data found in files—such as Markdown—and provide metadata to the markdown files via YAML frontmatter. The metadata types are factors like an author for a post or a price for a product.

Deploy

jamstack: rocket taking off

We have already established that we, as developers, need to pre-render markup using a tool (a static site generator), and we need to then deploy that site somehow to a CDN network.

There are many ways to publish and deploy applications, using services such as Netlify, AWS Amplify, and Zeit Now. They all push our pre-rendered Markup to a CDN. Why is this useful? CDNs do automatic load balancing, and they will always serve the content to the closest requesting user based on their geographical location.

Historically speaking, invalidating the CDN cache has been difficult. Invalidating a CDN cache means that if a new version of the app is available, it shouldn't be cached anywhere on the CDN because some visitors could get 'stale' data. All the services, as mentioned earlier, take care of cache invalidation automatically.

Furthermore, from a developer perspective, atomic changes can be very quickly deployed. Typically the workflow looks like this: developers working on some code execute a git push and commit. The deployment service notices that there's a new commit to git, and starts a redeployment process, which includes the pre-rendering and the cache invalidation again.

"Because of the pre-rendered, non-origin server aspect of the stack, the sites are by default going to be faster."

A service, such as Netlify, will keep all the deployments in its history, and rolling back to a previous version of the app is just a matter of a click.

Using the JAMstack has multiple other benefits to end-users and developers as well. End users obviously will be able to receive updates/changes to the site faster, and because of the pre-rendered, non-origin server aspect of the stack, the sites are by default going to be faster.

Developers and development teams can benefit from the stack from a lost of reasons. First and foremost, they don't need to manage servers, and there are fewer DevOps related tasks being added to standard development related tasks. Even when some server-side code execution is required, Serverless Functions can come to the rescue.

Security in the JAMstack is also available out of the box. If we think about the LAMP stack, there are many servers involved—application servers, database servers—each connecting one to the other, each executing code and queries. The attack surface area is rather large.

In the JAMstack there's no server-side code execution, and by default, all the site content is "static", and it's placed on a CDN server. The attack surface area is a lot smaller.

Don't get confused by the term "static" here though. The fact that the JAMstack uses something called a static site generator doesn't mean that the site is just plain old HTML.

We discussed earlier that the 'J' (JavaScript) is for adding dynamic features and interactivity to the application. Client-side JavaScript can be used to enhance the application by consuming APIs, using SDKs, and even to employ hydration.

You might also like: Website Security: 13 Ways to Improve Front End Security and Not Get Hacked.

Good for business

Businesses can also capitalize on the fact that planning a project with the JAMstack is a lot easier, and the costs are a lot clearer. Cost calculation can be easily done because there's no need to purchase servers, but instead, service time can be bought, which is a lot easier to calculate. Generally speaking, there's less relying on operations because there's no need to manage physical servers. 

Furthermore, talking about costs, it's essential to mention the cost of developers. Previously, we mentioned how developers could focus on development, which means that their time is spent on doing what they are supposed to do, and not on DevOps and other infrastructure management related tasks, which also leads to some cost-saving.

The JAMstack is a solid decision not only for the development benefits it brings, but also for the business advantages it can provide.

Template Icon

Dynamic by nature

The JAMstack has multiple benefits to both the end-user and the developers, and it's certainly a stack that you should give a try. It enables a better user experience and a better overall development workflow. Don't be shy to leverage some of the great services out there to make your otherwise static application dynamic in nature.

Have you already developed with the JAMstack? Share your experiences below.

About the Author

Tamas Piros is a Google Developer Expert in Web Technologies, a Developer Evangelist for Cloudinary, and director of Full Stack Training. He has more than a decade of experience delivering technical training to large, prestigious organizations. Throughout his career, he has delivered presentations and training classes all over the world. He’s passionate about unlocking the latest and greatest features of web development. Tamas currently runs jamstack.training, which delivers video courses related to the JAMstack.

Grow your business with the Shopify Partner Program

Learn more