Getting to the glass
approaches to rendering views on the web

Phil Hawksworth, Netlify

Getting to the glassGetting to the glass

JavaScript dates + Daylight saving

January 32th

Getting to the glassGetting to the glass

“Time to glass”

ServerClientAll the magicthat does the things
that gets the stuff
to the place

All the magic that does
the things that gets theGetting
stuff totothe
theplaceglass
approaches to rendering views on the web

Phil Hawksworth, Netlify

oh, hello
Phil Hawksworth
According to my family, I work in computersoh, hello
Phil Hawksworth
According to my family, I work in computers

nIdekniLsdah reToh, hello

Tw i t te r

G i tH u@ PhilHawksworth
Developer Relations, Netlify

Bl ueS k ynodo
M as tb

How do we do the best job ofgetting to the glass?

*It depends* more on that later

Trends inweb development
are cyclicalPendulumPendulumPendulumPendulumPendulumPendulum
ExtremeExtremePendulum
ExtremeExtremeThe sweet spotIt depends

G / ISR / ODB / SPA / MPA / ESR
PA / MPA / SSR / CSR / SSG / D/ SPA / MPA / SSR / CSR / SSG/ SSR / CSR / SSG / DPR / DSG
SSR / CSR / SSG / DPR / DSG /ESR / ISR / ODB / SPA / MPA /It depends
Requirements / Costs / Time / Skills / Sustainability…

But…

Simplicity

is always something to strive for

The principle ofleast power

https://www.w3.org/2001/tag/doc/leastPower.html

Computer Science […] spent a lot of effort making
languages which were as powerful as possible.
Nowadays we have to appreciate the reasons for picking
not the most powerful solution but the least powerful— Tim Berners-Lee

https://www.w3.org/DesignIssues/Principles.html#PLP

Simplify as much as possible
But no more

Pendulum
Complexity

Simplicity

Pragmatic

How do we do the best job ofgetting to the glass?

G / ISR / ODB / SPA / MPA / ESR
PA / MPA / SSR / CSR / SSG / D/ SPA / MPA / SSR / CSR / SSG/ SSR / CSR / SSG / DPR / DSG
SSR / CSR / SSG / DPR / DSG /ESR / ISR / ODB / SPA / MPA /Pendulum
Client render

Server render?

All the magicthat does the things
that gets the stuff
to the placeServer-side

BuildServer

Client-side

Client!
?
yll
re aServer-side

BuildServer

Edge-side

Client-side

Edge

ClientGenerate
our pages

Enhanceour pages

Display
our pages

BUILD

EDGE

CLIENTPOTENTIALLY

BORINGI’m excited about
this pattern— Shameless display of feelings,
Phil Hawksworth,
Just nowSOME BORING
EXAMPLEWhat’sWhat’s

This website utilizes technologies such as cookies to enable essential site functionality, as well as for analytics, personalization, andtargeted advertising purposes. You may change your settings at any time or accept the default settings.
You may close this banner to continue with only essential cookies, but we’d prefer you to accidentally press the big Accept button
Cookie Policy

AcceptReview

What’s

This website utilizes technologies such as cookies to enable essential site functionality, as well as for analytics, personalization, andtargeted advertising purposes. You may change your settings at any time or accept the default settings.
You may close this banner to continue with only essential cookies, but we’d prefer you to accidentally press the big Accept button
Cookie Policy

AcceptReviewCOOL?

We use cookies because, well, we have to. Click "Accept" if you want toproceed - if not, tough luck. Manage your preferences if you dareby clicking
What’s"Cookie Settings”.
We gather data through cookies to tailor content, track our traﬃc, and forsome social media stuﬀ. By accepting, you've committed. Read about it in
our Privacy Policy if you care. Click the link to enlighten yourself.

Your privacy matters, but so does our need for cookies. Hit "Accept All" if you
have no choice. Choices are limited here. Adjust your settings in our Cookie
Settings - or risk the consequences.
Cookies make our site snazzy. Click "Accept All Cookies" or face theconsequences. No turning back. Tinker with your cookie settings, if you dare,
and uncover our cookie schemes in the Cookie Policy link.am. We are here toassist you and ensure that your browsing experience is both enjoyable andsecure.

AcceptReviewDisplay
conditionalInterfaceSOControlcookies

Third-party
client-side
JavaScript

Performancekillers
BUT

TerribleinterfaceWhat’sWhat’sServer-sideServer

Edge-side

Client-side

EdgeClient````

No JavaScript

No client-side JavaScript

HTML arrives completeLocation aware
Without needing permission

Sandboxed from other site code
Yet under control of site owners

An edge function example
netlify/edge-functions/hello.ts

export default () =>" new Response("Hello world");
export const config = {path: "/hello"};`An edge function example
netlify/edge-functions/cookie-consent.ts

import { Context } from “@netlify/edge-functions";
import myCookieBannerTemplate from './utils/banner.js';
import cookiePolicyCountries from'./utils/territories.js';`

export default async (request: Request, context: Context) =>" {const countryCode = context.geo?.country?.code;import { Context } from “@netlify/edge-functions";
importmyCookieBannerTemplatefrom'./utils/banner.js';
An edge function example

import cookiePolicyCountries from './utils/territories.js';
netlify/edge-functions/cookie-consent.ts

export default async (request: Request, context: Context) =>" {const countryCode = context.geo?.country?.code;`// Show the cookie banner to visitors from the correct countries
if(cookiePolicyCountries.includes(countryCode)) {// Get the HTTP response content
const response = await context.next();

export default async (request: Request, context: Context) =>" {An edge function example

const countryCode = context.geo?.country?.code;
netlify/edge-functions/cookie-consent.ts// Show the cookie banner to visitors from the correct countries
if(cookiePolicyCountries.includes(countryCode)) {// Get the HTTP response content
const response = await context.next();`

const page = await response.text();// Insert the UI just before the end of the body tag
const ui = myCookieBannerTemplate(countryCode);
const regex = /<\/body>/i;if(cookiePolicyCountries.includes(countryCode)) {An edge function example// Get the HTTP response content
netlify/edge-functions/cookie-consent.ts
const response= await context.next();

const page = await response.text();// Insert the UI just before the end of the body tag
const ui = myCookieBannerTemplate(countryCode);
const regex = /<\/body>/i;`

const updatedPage = page.replace(regex, ui);
return new Response(updatedPage, response);}}`Generate
our pages

Enhanceour pages

Display
our pages

BUILD

EDGE

CLIENTPOTENTIALLYFramework freeFramework agnostic

Generate
our pages

Enhanceour pages

Display
our pages

BUILD

EDGE

CLIENTPOTENTIALLYLocalised times

Localized times

Pricing dataand stock levels

How well does it work?

How well does itFAIL?

Will they notice?

ANOTHERBORING
EXAMPLEGlobal navigationVAVNANAGAEGEMM

Global navigation

Global footer

But what aboutdata that’s notclose to the edge?

Many sites
Many stacks
Many brand teams
Many headaches when trying to keepthem all consistent, and the various
legal and compliance teams happy

SSIFFS. Not another TLA

Server-side

BuildServer

Edge-side

Client-side

Edge

ClientAn edge include
functionutility
exampleany-old-page.html<edge-include href=“https://example.com/global-footer.html“ />`An edge include
functionutility
exampleany-old-page.html<edge-include href=“https://example.com/global-footer.html“><footer><ul><li><a href="/">Home</a></li>`<li><a href="/legal">Legal</a></li><li><a href="/styleguide">Styleguide</a></li></ul></footer></edge-include>element.replace(html, { html: true });} include
An edgefunctionutility
example}}netlify/edge-functions/include.ts

export default async (request: Request, context: Context) =>" {const resp = await context.next();
return new HTMLRewriter().on('edge-include', new UserElementHandler()).transform(resp);};`An edge include
functionutility
examplenetlify/edge-functions/include.ts

class UserElementHandler {async element(element) {// Go get it
const url = element.getAttribute('href');
let response = await fetch(new Request(url));
if(response.ok) {`// Replace the custom element with the content
let html = await response.text();
element.replace(html, { html: true });}}}An edge include
functionutility
examplenetlify/edge-functions/include.ts

class UserElementHandler {async element(element) {// Go get it
const url = element.getAttribute('href');
let response = await fetch(new Request(url));
if(response.ok) {`// Replace the custom element with the content
let html = await response.text();
element.replace(html, { html: true });
}
}}

EN
DO

T
S
AFE
N
DO

Generate
our pages

Enhanceour pages

Display
our pages

BUILD

EDGE

CLIENTPOTENTIALLYBut what aboutdata that’s notclose to the edge?

Making edge rendering fast

DataAPI

Source API

Function

SWR

Edge
Edge Function

A similar emerging pattern

PPR
Partial Prerendering

Generate
our pages

Enhanceour pages

Display
our pages

BUILD

EDGE

CLIENTPOTENTIALLYGenerate
our pages

Requestand stream
enhancements

Updateour pages

BUILD / SSREDGE

CLIENTPOTENTIALLY

Pendulum
Monolithic

DecoupledDid we learn anything?

Rendering patterns
are yours to control

Understand requirements.
Make choices.

Start simple.

Do as much as possible
in advanceDon’t be hypnotised bythe pendulumIt depends

Should I piss off Cookie Monster?

NoAttributions and resources
Links
https://twitter.com/philhawksworth
https://hawksworx.com
https://edge-functions-examples.netlify.app/
https://developers.netlify.com/guides/how-to-make-edge-rendering-fast/
https://developers.netlify.com/guides/partial-prerendering-without-a-framework/

Imageshttps://unsplash.com/photos/clear-drinking-glass-with-orange-liquid-4aWCVJA2uSo
https://unsplash.com/photos/a-tall-glass-sitting-on-top-of-a-table-fiN073Jt5L8
https://unsplash.com/photos/turned-on-flat-screen-monitor-6j_lmeycTrMhttps://unsplash.com/photos/brown-and-black-floral-wreath-6BMjuiB_IF0
https://www.flickr.com/photos/tangledcontrolpads/639854414/in/photostream/
https://unsplash.com/photos/bonfire--98jVaVuGv0

Thanks@philhawksworth