JAMstack

A new web app architecture

Webmontag Dresden - 22.07.19

About me

Alexander Lichter

Nuxt.js Core Team Member

@TheAlexLichter

A quick Time travel

through the history of web development

So it all began..

Server

1. Request

2. HTML

Dynamic Websites

Backend

1. Request

4. Dynamically generated HTML

DB

2. Query

3. Results

But: "Click and wait" for every page

AJAX and JavaScript

Server

1. Request

2. HTML

3. AJAX Request

4. XML (oder JSON)

The age of SPAs

CDN

1. Request

2. Return Javascript

3. Parsing

API

4. Request

5. Response

Advantages

  • No full reload on further navigation
  • Better UX compared to "click and wait"

Problems

  • Slow Time to first paint (due to parsing)
  • White screen / flash of content
  • Javascript generates HTML -> bad SEO
  • mediocre UX for initial page load

Why not best of both worlds?

Traditional SSR

SPA

Server Side Rendering

Node.js

Server

1. Request

4. HTML + JS

API

2. Request

3. JSON

5. Hydration after JS Download

optional

5. Request

6. JSON

And now?

"Modern" SSR

SPA

Traditional SSR

"Old" Static pages

Single Page Apps

Server Side Rendering

JAMstack

JAMstack

J

A

M

avascript

PIs

arkup

  • Static, won't be modified by server

  • Generated on build-time (before (re-)deploying)

  • Usually compiled/built via Static Site Generator (SSG)

Markup

<template>
  <p class="demo">
    <button class="btn-primary" @click.prevent="handleClick">
      <slot></slot>(clicked - {{count}})
    </button>
  </p>
</template>

Example (Vue)

  • Responsible for the website's dynamics

  • Only on client-side

  • Independent of frameworks or libraries

Javascript

  • Used for interacting with the website (comments, forms...)

  • Called through Javascript and HTTPS

  • Good fit: Microservices, Serverless Functions or similar

APIs

Beispiel (serverless fn)

import { promisify } from 'util'
import sendmail from 'sendmail'

const shouldSend = process.env.SEND_MAIL

exports.handler = async (event) => {
  if (event.httpMethod !== 'POST') {
    return { statusCode: 405, body: JSON.stringify({ 'error': 'Method not allowed' }) }
  }
  try {
    const params = JSON.parse(event.body)
    const attributes = ['name', 'email', 'msg']
    const sanitizedAttributes = attributes.map(n => validateAndSanitize(n, params[n]))
    const someInvalid = sanitizedAttributes.some(r => !r)

    if (someInvalid) {
      return { statusCode: 422, body: JSON.stringify({ 'error': 'Ugh.. That looks unprocessable!' }) }
    }

    const sendMail = (name, email, msg) => pSendMail({
      from: email,
      to: process.env.MAIL_TO,
      subject: 'New contact form message',
      text: msg
    })

    try {
      await sendMail(...sanitizedAttributes)
      return { statusCode: 200, body: JSON.stringify({ 'message': 'OH YEAH' }) }
    } catch (e) { /* */ }
  } catch (_) { /* */}
}

TL;DR

Create your page

via SSG

Upload your code

via Git

Build your page with your SSG

Deploy the static Files via CDN or similar

Done!

But why JAMstack?

Performance

Simplicity

Security

Cost

Simplicity

  • Only static HTML files, no .php / .py / ...
  • You don't need a server*
  • No difficult deploy pipelines anymore!

*hosting via. GitHub pages oder Netlify

Security

  • No content generated "on the fly". Static files!
  • API endpoints are small and ideally isolated
  • Good practice: "Content API" only available at build time

Performance

  • Improved Time to first Byte due to CDN
  • Easy Cache Invalidation
  • Quick Response Time as it is just HTML
  • Ideal for SEO

Cost

  • No server, no server fees!
  • Free Hosting (via Netlify or GH Pages)
  • Serverless APIs are billed by usage

When not to go for JAMstack?

Highly dynamic (and SEO-related) Data

Better go for "modern" SSR (e.g. with Nuxt)

Live Demo? Live Demo!

Further reading

Nuxt.js - An Introduction - Slides of my Nuxt Intro

JAMstack.org - More about JAMstack

Made with Slides.com