Slide 1

Slide 1 text

The Unbearable Weight of Massive JavaScript

Slide 2

Slide 2 text

twnsnd.com/perfnow

Slide 3

Slide 3 text

twnsnd.com/perfnow How did our priorities get misaligned? What it really means to be productive How we can improve things with the Web Platform

Slide 4

Slide 4 text

twnsnd.com/perfnow Web Platform- fi rst

Slide 5

Slide 5 text

twnsnd.com/perfnow

Slide 6

Slide 6 text

twnsnd.com/perfnow Up to 2 years 3 to 5 years 5 to 10 years 10 to 20 years How long?! 😬 0% 1,600% Years of Experience

Slide 7

Slide 7 text

twnsnd.com/perfnow img.png { behavior: url(png.htc) }

Slide 8

Slide 8 text

twnsnd.com/perfnow No ever-green browsers Front-end development ‘Not SERIOUS’ Inaccessible Macromedia Adobe Flash What even is ‘Automated testing’? Rudimentary web performance tooling

Slide 9

Slide 9 text

twnsnd.com/perfnow Reach a global audience Iterate faster than any other platform Lower disparity in connectivity and compute ‘Progressive Enhancement’ and ‘Graceful Degradation’ coined Web Standards movement headway on consistency

Slide 10

Slide 10 text

Real world projects BIG TECH & VC DEMOS

Slide 11

Slide 11 text

twnsnd.com/perfnow

Slide 12

Slide 12 text

twnsnd.com/perfnow

Slide 13

Slide 13 text

twnsnd.com/perfnow Trickle-down User Experience

Slide 14

Slide 14 text

twnsnd.com/perfnow “92% [of businesses] think their website’s poor user experience is costing them sales” — Storyblok Research

Slide 15

Slide 15 text

twnsnd.com/perfnow Janky sliders Multi-megabyte JavaScript resources for static landing pages Tracking-dependent add-to-cart Unhoverable mega-menus In fi nite loops Skeletons for infrequently changed content Accept cookies! Live chat now! Sign-up for 10% o ff ! Client-side rendered forms 2.5mb marketing landing pages

Slide 16

Slide 16 text

twnsnd.com/perfnow

Slide 17

Slide 17 text

twnsnd.com/perfnow

Slide 18

Slide 18 text

twnsnd.com/perfnow We can do better

Slide 19

Slide 19 text

twnsnd.com/perfnow Developer Experience Convenience

Slide 20

Slide 20 text

twnsnd.com/perfnow Productivity is more than n p m i ns ta l l

Slide 21

Slide 21 text

twnsnd.com/perfnow

Slide 22

Slide 22 text

twnsnd.com/perfnow Performance Accessibility Usability Talent Availability & Retention Maintainability Security Reliability & Robustness Onboarding & Training

Slide 23

Slide 23 text

twnsnd.com/perfnow Performance Accessibility Usability Talent Availability & Retention Maintainability Security Reliability & Robustness Onboarding & Training

Slide 24

Slide 24 text

twnsnd.com/perfnow A necessary but costly decision

Slide 25

Slide 25 text

twnsnd.com/perfnow

Slide 26

Slide 26 text

twnsnd.com/perfnow

Slide 27

Slide 27 text

twnsnd.com/perfnow Tell me you’ve migrated to an SPA without telling me you’ve migrated to an SPA

Slide 28

Slide 28 text

twnsnd.com/perfnow “It would be better if it was more ’APP-LIKE’” — Nobody, not a single end-user

Slide 29

Slide 29 text

twnsnd.com/perfnow

Slide 30

Slide 30 text

twnsnd.com/perfnow Consistently working Reasonably fast Accessible Usable

Slide 31

Slide 31 text

twnsnd.com/perfnow Performance Accessibility Usability Talent Availability & Retention Maintainability Security Reliability & Robustness Onboarding & Training “It depends”

Slide 32

Slide 32 text

twnsnd.com/perfnow Few are ready

Slide 33

Slide 33 text

twnsnd.com/perfnow Embracing the Web Platform

Slide 34

Slide 34 text

twnsnd.com/perfnow “Consider users over authors over implementors over speci fi ers over theoretical purity” — W3C’s Priority of Constituencies (within the HTML Design Principles) That’s us!

Slide 35

Slide 35 text

twnsnd.com/perfnow

Slide 36

Slide 36 text

twnsnd.com/perfnow 55,000 lines of JavaScript

Slide 37

Slide 37 text

twnsnd.com/perfnow 1. Import Maps 2. Custom Elements 3. Scroll-snapping / Scroll-linked Animations 4. View Transitions 5. Navigation API

Slide 38

Slide 38 text

twnsnd.com/perfnow BUT FIRST! A few important words on approach

Slide 39

Slide 39 text

twnsnd.com/perfnow Progressive Enhancement

Slide 40

Slide 40 text

twnsnd.com/perfnow Sending useful HTML: forms, links, buttons Accepting there will be bugs in your software Ensuring every feature works without JavaScript, regardless of importance Going cold-turkey on frameworks & libraries

Slide 41

Slide 41 text

twnsnd.com/perfnow Browser support

Slide 42

Slide 42 text

twnsnd.com/perfnow

Slide 43

Slide 43 text

twnsnd.com/perfnow

Slide 44

Slide 44 text

twnsnd.com/perfnow Waiting for all browsers to support a feature Waiting for everyone to update their browser Developing against the lowest common denominator Using features which bene fi t signi fi cant portions of your customer base

Slide 45

Slide 45 text

twnsnd.com/perfnow Poly fi lls, Shims & alternative code paths

Slide 46

Slide 46 text

twnsnd.com/perfnow Making it work for everyone, regardless of performance impact Using poly fi lls that provide support back to the stone age Using massive fully-featured poly fi lls, when an if/else would do Never reviewing what poly fi lls you still have in play Giving more of your customer base a great experience

Slide 47

Slide 47 text

twnsnd.com/perfnow Import Maps Shimmable!

Slide 48

Slide 48 text

twnsnd.com/perfnow { "imports": { "shared-library-1.js": "./shared-library-1-a1b2c3.js", "shared-library-2.js": "./shared-library-2-d4e5f6.js" } }

Slide 49

Slide 49 text

twnsnd.com/perfnow import { feature } from "shared-library-1.js"; /* actually loads shared-library-1-a1b2c3.js */

Slide 50

Slide 50 text

twnsnd.com/perfnow { "imports": { "third-party.js": "https://example.com/third-party.js" } } JUST BECAUSE YOU CAN, DOESN’T MEAN YOU SHOULD

Slide 51

Slide 51 text

twnsnd.com/perfnow shared-library.js file-one.js file-two.js file-three.js import { feature } from "shared-library.js"

Slide 52

Slide 52 text

twnsnd.com/perfnow shared-library-v1.js file-one-v1.js file-two-v1.js file-three-v1.js import { feature } from "shared-library-v1.js"

Slide 53

Slide 53 text

twnsnd.com/perfnow shared-library-v2.js file-one-v1.js file-two-v1.js file-three-v1.js import { feature } from "shared-library-v1.js"

Slide 54

Slide 54 text

twnsnd.com/perfnow shared-library-v2.js file-one-v1.js file-two-v1.js file-three-v1.js import { feature } from "shared-library-v2.js"

Slide 55

Slide 55 text

twnsnd.com/perfnow shared-library-v2.js file-one-v2.js file-two-v2.js file-three-v2.js import { feature } from "shared-library-v2.js"

Slide 56

Slide 56 text

twnsnd.com/perfnow Improved cache hit ratio More simple, faster build pipelines Lower reliance on bundling * YMMV - see shared dictionarY compression Therefore, better prioritisation of individual scripts Import Maps

Slide 57

Slide 57 text

twnsnd.com/perfnow { "imports": { "shared-import.js": "./shared-import-e5f6.js" } }

Slide 58

Slide 58 text

twnsnd.com/perfnow

Slide 59

Slide 59 text

twnsnd.com/perfnow Shadow DOM Light DOM

Slide 60

Slide 60 text

twnsnd.com/perfnow Shadow DOM Light DOM

Slide 61

Slide 61 text

twnsnd.com/perfnow ... ... ...

Slide 62

Slide 62 text

twnsnd.com/perfnow class MyCustomElement extends HTMLElement { connectedCallback() { // added to DOM, attach events, initialize etc } disconnectedCallback() { // removed from DOM, detach events, cleanup etc } } customElements.define("my-custom-element", MyCustomElement)

Slide 63

Slide 63 text

twnsnd.com/perfnow class MyCustomElement extends HTMLElement { static get observedAttributes() { return ["my-attribute"] } attributeChangedCallback(name, oldValue, newValue) { // action attribute changes } }

Slide 64

Slide 64 text

twnsnd.com/perfnow class MyCustomElement extends HTMLElement { static observedAttributes = ["value"] static formAssociated = true #internals constructor() { super() this.#internals = this.attachInternals() } attributeChangedCallback(name, oldValue, newValue) { this.#internals.setFormValue(newValue) } }

Slide 65

Slide 65 text

twnsnd.com/perfnow my-custom-element:defined { /* active styling */ } my-custom-element:not(:defined) { /* inactive styling */ }

Slide 66

Slide 66 text

twnsnd.com/perfnow You may not need to use slots or the (Declarative) Shadow DOM Your custom element can just use querySelector and innerHTML You may not need isomorphic rendering Some duplication is probably fi ne (though, alternatives do exist) Don’t over-complicate it LIT, WEBC, ENHANCE

Slide 67

Slide 67 text

twnsnd.com/perfnow Scroll Snapping & Scroll-Linked Animations

Slide 68

Slide 68 text

twnsnd.com/perfnow Progressive Enhancement ~10 lines of CSS Zero JavaScript GPU-accelerated Scroll Snap

Slide 69

Slide 69 text

twnsnd.com/perfnow .parent { overflow: hidden; overflow-x: auto; scroll-snap-type: x mandatory; scroll-snap-stop: always; scroll-behavior: smooth; overscroll-behavior-inline: contain; -webkit-overflow-scrolling: touch; scrollbar-width: none; } .parent::-webkit-scrollbar { display: none } .parent > * { scroll-snap-align: start }

Slide 70

Slide 70 text

twnsnd.com/perfnow

Slide 71

Slide 71 text

twnsnd.com/perfnow Progressive Enhancement ~10 lines of CSS Zero JavaScript Poly fi lled with Intersection Observer Scroll-Linked Animation (Position: Support) IMPLEMENTATION EN-ROUTE!

Slide 72

Slide 72 text

twnsnd.com/perfnow @supports (scroll-timeline: --name inline) { @keyframes fade-in { 0% { opacity: 0 } 1% { opacity: 1 } } scrollable-element { scroll-timeline: --scroll-shadow inline; } scrollable-element .scroll-shadow-inline-start, scrollable-element .scroll-shadow-inline-end { animation: auto fade-in linear forwards; animation-timeline: --scroll-shadow; } scrollable-element .scroll-shadow-inline-end { animation-direction: reverse; } }

Slide 73

Slide 73 text

twnsnd.com/perfnow if (!CSS.supports("(scroll-timeline: --name inline)")) { customElements.define("scroll-indicator", ScrollIndicator) if (window.matchMedia("(min-width: 1024px)").matches) { customElements.define("scroll-shadow", ScrollShadow) } }

Slide 74

Slide 74 text

twnsnd.com/perfnow View Transitions

Slide 75

Slide 75 text

twnsnd.com/perfnow SPAs are a big trade-o ff just for page transitions

Slide 76

Slide 76 text

twnsnd.com/perfnow Nobody likes having their toys taken away

Slide 77

Slide 77 text

twnsnd.com/perfnow Progressive Enhancement As little as 1 line of HTML Zero JavaScript GPU-accelerated Cross-document Transitions (Position:UNKNOWN)

Slide 78

Slide 78 text

twnsnd.com/perfnow

Slide 79

Slide 79 text

twnsnd.com/perfnow view-transition-name: my-element

Slide 80

Slide 80 text

twnsnd.com/perfnow ::view-transition-old(my-element) { animation: fade 0.3s ease forwards } ::view-transition-new(my-element) { animation: fade 0.3s ease reverse } @keyframes fade { from { opacity: 1 } to { opacity: 0 } }

Slide 81

Slide 81 text

twnsnd.com/perfnow

Slide 82

Slide 82 text

twnsnd.com/perfnow Progressive Enhancement ~5 lines of JavaScript (inc. fallback) Customise with CSS GPU-accelerated Single-document Transitions (Position:POSITIVe/SUPPORT)

Slide 83

Slide 83 text

twnsnd.com/perfnow function navigateWithTransition(data) { // fallback if (!document.startViewTransition) { updateDOM(data) return } document.startViewTransition(() => updateDOM(data)) }

Slide 84

Slide 84 text

twnsnd.com/perfnow Navigation API (Position: POSITIVE/Support)

Slide 85

Slide 85 text

twnsnd.com/perfnow Manually attach submit/click event listeners Manually implement loading feedback Manually announce page changes Manually manage scroll position History API

Slide 86

Slide 86 text

twnsnd.com/perfnow navigation.addEventListener("navigate", (event) => { if (!event.canIntercept) return event.intercept({ async handler() { const content = await loadContent(event.destination.url) renderContent(content) } }) })

Slide 87

Slide 87 text

twnsnd.com/perfnow navigation.addEventListener("navigate", (event) => { if (!event.canIntercept) return event.intercept({ async handler() { const content = await loadContent(event.destination.url) document.startViewTransition(() => renderContent(content)) } }) })

Slide 88

Slide 88 text

twnsnd.com/perfnow Decoupled from the DOM Native browser loading state Native accessibility technology integration Handles restoring scroll position for you Navigation API

Slide 89

Slide 89 text

twnsnd.com/perfnow Bonus noteworthy mentions

Slide 90

Slide 90 text

twnsnd.com/perfnow CSS Toggles

Slide 91

Slide 91 text

twnsnd.com/perfnow • Push Notifications • Badging API • WebShare API • PassKeys • Anchor Positioning • Container Queries • Cascade Layers • :user-valid / :user-invalid • Popover API • Deferred Fetch • Internationalisation API • Web Workers • OffscreenCanvas • WASM

Slide 92

Slide 92 text

twnsnd.com/perfnow Use the Web Platform, don’t reimplement it

Slide 93

Slide 93 text

twnsnd.com/perfnow How’re those stats looking?

Slide 94

Slide 94 text

twnsnd.com/perfnow 55,000650 lines of JavaScript

Slide 95

Slide 95 text

twnsnd.com/perfnow

Slide 96

Slide 96 text

twnsnd.com/perfnow

Slide 97

Slide 97 text

twnsnd.com/perfnow 1. Know your audience 2. Don’t limit yourself to fully-adopted features 3. Consider the standard positions of browsers, not just support 4. Consider the maturity of standards 5. Consider how far back and how wide your poly fi lls need to go

Slide 98

Slide 98 text

twnsnd.com/perfnow Thank you!