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”

Server Client

All the magic that does the things that gets the stuff to the place

All the magic that does the things that gets the Getting stuff totothe theplace glass 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

n I d e k n i L s d a h re T oh, hello Tw i t te r G i tH u @ PhilHawksworth Developer Relations, Netlify Bl ueS k y n o d o M as t b

How do we do the best job of getting to the glass?

  • It depends
  • more on that later

Trends in web development are cyclical

Pendulum

Pendulum

Pendulum

Pendulum

Pendulum

Pendulum Extreme Extreme

Pendulum Extreme Extreme The 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 of least 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 of getting 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 magic that does the things that gets the stuff to the place

Server-side Build Server Client-side Client

! ? y l l re a Server-side Build Server Edge-side Edge Client-side Client

Generate our pages Enhance our pages Display our pages BUILD EDGE CLIENT POTENTIALLY

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, and targeted 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 Accept Review

What’s This website utilizes technologies such as cookies to enable essential site functionality, as well as for analytics, personalization, and targeted 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 Accept Review

COOL? We use cookies because, well, we have to. Click “Accept” if you want to proceed - if not, tough luck. Manage your preferences if you dare by clicking What’s “Cookie Settings”. We gather data through cookies to tailor content, track our traffic, and for some social media stuff. 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 the consequences. 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 to assist you and ensure that your browsing experience is both enjoyable and secure. Accept Review

Display conditional Interface SO Control cookies Third-party client-side JavaScript Performance killers BUT Terrible interface

What’s

What’s

Server-side Server Edge-side Edge Client-side Client

`

`

`

`

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”; An import myCookieBannerTemplate from ‘./utils/banner.js’; 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 Enhance our pages Display our pages BUILD EDGE CLIENT POTENTIALLY

Framework free

Framework agnostic

Generate our pages Enhance our pages Display our pages BUILD EDGE CLIENT POTENTIALLY

Localised times

Localized times

Pricing data and stock levels

How well does it work?

How well does it FAIL ?

Will they notice?

ANOTHER BORING EXAMPLE

Global navigation

V A V N A N A G A E G E M M

Global navigation

Global footer

But what about data that’s not close to the edge?

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

SSI FFS. Not another TLA

Server-side Build Server Edge-side Edge Client-side Client

An edge include functionutility example any-old-page.html <edge-include href=“https://example.com/global-footer.html“ /> `

An edge include functionutility example any-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 edge functionutility 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 example netlify/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 example netlify/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 }); } } }

E N DO T S A F E N DO Generate our pages Enhance our pages Display our pages BUILD EDGE CLIENT POTENTIALLY

But what about data that’s not close to the edge?

Making edge rendering fast Data API Source API Function SWR Edge Edge Function

A similar emerging pattern

PPR Partial Prerendering

Generate our pages Enhance our pages Display our pages BUILD EDGE CLIENT POTENTIALLY

Generate our pages Request and stream enhancements Update our pages BUILD / SSR EDGE CLIENT POTENTIALLY

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 by the 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/ Images https://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_lmeycTrM https://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