Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Unbearable Weight of Massive JavaScript – performance.now()

Ryan Townsend
November 01, 2023

The Unbearable Weight of Massive JavaScript – performance.now()

Follow Ryan on Mastodon @ https://webperf.social/@ryantownsend

For the past 10+ years, JavaScript frameworks and Single Page Applications have been marketed as the solution to all our performance, robustness and productivity problems, but things haven’t worked out the way we’d all hoped, have they?

* Simple marketing and ecommerce sites are still getting heavier and slower.

* Features fail in weird and wonderful ways meaning we need an ever-increasing array of tooling to monitor and debug problems.

* Teams armed with the latest Apple Silicon Macs, expensive CI tooling and complex build pipelines still can’t ship effectively.

But it’s not all doom-and-gloom: we live in a time of unprecedented opportunity to give our users a fantastic experience – the web platform has never been more capable than it is today.

Let’s look at what we can achieve by simplifying our web architecture, utilising new and upcoming Web Platform APIs and getting back to building fast, maintainable, user-friendly front-ends.

Ryan Townsend

November 01, 2023
Tweet

More Decks by Ryan Townsend

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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!
  7. twnsnd.com/perfnow 1. Import Maps 2. Custom Elements 3. Scroll-snapping /

    Scroll-linked Animations 4. View Transitions 5. Navigation API
  8. 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
  9. 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
  10. 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
  11. 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
  12. twnsnd.com/perfnow <script type="importmap"> { "imports": { "shared-import.js": "./shared-import-e5f6.js" } }

    </script> <script src="script-1-a1b2.js" type="module"></script> <script src="script-2-c3d4.js" type="module"></script>
  13. twnsnd.com/perfnow <my-custom-element> <img src="..." width="200" height="200" alt="..." /> <img src="..."

    width="200" height="200" alt="..." /> <img src="..." width="200" height="200" alt="..." /> </my-custom-element>
  14. 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)
  15. twnsnd.com/perfnow class MyCustomElement extends HTMLElement { static get observedAttributes() {

    return ["my-attribute"] } attributeChangedCallback(name, oldValue, newValue) { // action attribute changes } }
  16. 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) } }
  17. 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
  18. 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 }
  19. 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!
  20. 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; } }
  21. twnsnd.com/perfnow Progressive Enhancement As little as 1 line of HTML

    Zero JavaScript GPU-accelerated Cross-document Transitions (Position:UNKNOWN)
  22. 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 } }
  23. twnsnd.com/perfnow Progressive Enhancement ~5 lines of JavaScript (inc. fallback) Customise

    with CSS GPU-accelerated Single-document Transitions (Position:POSITIVe/SUPPORT)
  24. twnsnd.com/perfnow Manually attach submit/click event listeners Manually implement loading feedback

    Manually announce page changes Manually manage scroll position History API
  25. twnsnd.com/perfnow navigation.addEventListener("navigate", (event) => { if (!event.canIntercept) return event.intercept({ async

    handler() { const content = await loadContent(event.destination.url) renderContent(content) } }) })
  26. 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)) } }) })
  27. twnsnd.com/perfnow Decoupled from the DOM Native browser loading state Native

    accessibility technology integration Handles restoring scroll position for you Navigation API
  28. 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
  29. 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