Getting to the Glass

A presentation at Smashing Conference Freiburg 2024 in September 2024 in Freiburg, Germany by Phil Hawksworth

Slide 1

Slide 1

Getting to the glass approaches to rendering views on the web Phil Hawksworth, Netlify

Slide 2

Slide 2

Getting to the glass

Slide 3

Slide 3

Getting to the glass

Slide 4

Slide 4

JavaScript dates + Daylight saving January 32th

Slide 5

Slide 5

Slide 6

Slide 6

Slide 7

Slide 7

Slide 8

Slide 8

Getting to the glass

Slide 9

Slide 9

Getting to the glass

Slide 10

Slide 10

“Time to glass”

Slide 11

Slide 11

Server Client

Slide 12

Slide 12

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

Slide 13

Slide 13

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

Slide 14

Slide 14

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

Slide 15

Slide 15

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

Slide 16

Slide 16

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

Slide 17

Slide 17

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

Slide 18

Slide 18

  • It depends
  • more on that later

Slide 19

Slide 19

Trends in web development are cyclical

Slide 20

Slide 20

Pendulum

Slide 21

Slide 21

Pendulum

Slide 22

Slide 22

Pendulum

Slide 23

Slide 23

Pendulum

Slide 24

Slide 24

Pendulum

Slide 25

Slide 25

Pendulum Extreme Extreme

Slide 26

Slide 26

Pendulum Extreme Extreme The sweet spot

Slide 27

Slide 27

It depends

Slide 28

Slide 28

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 /

Slide 29

Slide 29

It depends Requirements / Costs / Time / Skills / Sustainability…

Slide 30

Slide 30

But…

Slide 31

Slide 31

Simplicity is always something to strive for

Slide 32

Slide 32

The principle of least power https://www.w3.org/2001/tag/doc/leastPower.html

Slide 33

Slide 33

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

Slide 34

Slide 34

Simplify as much as possible But no more

Slide 35

Slide 35

Pendulum Complexity Simplicity

Slide 36

Slide 36

Pragmatic

Slide 37

Slide 37

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

Slide 38

Slide 38

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 /

Slide 39

Slide 39

Pendulum Client render Server render ?

Slide 40

Slide 40

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

Slide 41

Slide 41

Server-side Build Server Client-side Client

Slide 42

Slide 42

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

Slide 43

Slide 43

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

Slide 44

Slide 44

BORING

Slide 45

Slide 45

Slide 46

Slide 46

I’m excited about this pattern — Shameless display of feelings, Phil Hawksworth, Just now

Slide 47

Slide 47

SOME BORING EXAMPLE

Slide 48

Slide 48

What’s

Slide 49

Slide 49

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

Slide 50

Slide 50

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

Slide 51

Slide 51

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

Slide 52

Slide 52

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

Slide 53

Slide 53

What’s

Slide 54

Slide 54

What’s

Slide 55

Slide 55

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

Slide 56

Slide 56

`

Slide 57

Slide 57

`

Slide 58

Slide 58

`

Slide 59

Slide 59

`

Slide 60

Slide 60

No JavaScript

Slide 61

Slide 61

No client-side JavaScript

Slide 62

Slide 62

HTML arrives complete

Slide 63

Slide 63

Location aware Without needing permission

Slide 64

Slide 64

Sandboxed from other site code Yet under control of site owners

Slide 65

Slide 65

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

Slide 66

Slide 66

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;

Slide 67

Slide 67

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();

Slide 68

Slide 68

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;

Slide 69

Slide 69

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); } }

Slide 70

Slide 70

`

Slide 71

Slide 71

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

Slide 72

Slide 72

Framework free

Slide 73

Slide 73

Framework agnostic

Slide 74

Slide 74

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

Slide 75

Slide 75

Localised times

Slide 76

Slide 76

Localized times

Slide 77

Slide 77

Pricing data and stock levels

Slide 78

Slide 78

How well does it work?

Slide 79

Slide 79

How well does it FAIL ?

Slide 80

Slide 80

Will they notice?

Slide 81

Slide 81

ANOTHER BORING EXAMPLE

Slide 82

Slide 82

Slide 83

Slide 83

Slide 84

Slide 84

Slide 85

Slide 85

Slide 86

Slide 86

Global navigation

Slide 87

Slide 87

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

Slide 88

Slide 88

Slide 89

Slide 89

Slide 90

Slide 90

Global navigation

Slide 91

Slide 91

Global footer

Slide 92

Slide 92

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

Slide 93

Slide 93

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

Slide 94

Slide 94

SSI FFS. Not another TLA

Slide 95

Slide 95

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

Slide 96

Slide 96

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

Slide 97

Slide 97

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>

Slide 98

Slide 98

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); }; `

Slide 99

Slide 99

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 }); } } }

Slide 100

Slide 100

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 }); } } }

Slide 101

Slide 101

Slide 102

Slide 102

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

Slide 103

Slide 103

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

Slide 104

Slide 104

Slide 105

Slide 105

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

Slide 106

Slide 106

Slide 107

Slide 107

Slide 108

Slide 108

A similar emerging pattern

Slide 109

Slide 109

PPR Partial Prerendering

Slide 110

Slide 110

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

Slide 111

Slide 111

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

Slide 112

Slide 112

Pendulum Monolithic Decoupled

Slide 113

Slide 113

Slide 114

Slide 114

Slide 115

Slide 115

Did we learn anything?

Slide 116

Slide 116

Rendering patterns are yours to control

Slide 117

Slide 117

Understand requirements. Make choices. Start simple.

Slide 118

Slide 118

Do as much as possible in advance

Slide 119

Slide 119

Don’t be hypnotised by the pendulum

Slide 120

Slide 120

It depends

Slide 121

Slide 121

Should I piss off Cookie Monster?

Slide 122

Slide 122

No

Slide 123

Slide 123

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

Slide 124

Slide 124

Thanks @philhawksworth