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

🇬🇧 iJS London 2026 (Workshop)

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

🇬🇧 iJS London 2026 (Workshop)

React: Internals and Advanced Performance Patterns

Keeping user interfaces smooth becomes harder as React applications scale, especially across different devices, networks, and workloads. Understanding how React actually schedules and renders work can turn performance tuning from guesswork into engineering.

In this session, we’ll dive into React Fiber and reconciliation, connecting them to classic computer science concepts like cooperative scheduling and incremental work.

From there, we’ll explore practical strategies for production React apps, along with a few browser-level primitives that influence how quickly users actually see content. Finally, we’ll look at how to measure responsiveness in the real world using modern web performance tooling.

The goal is to build the mental models that let you reason about performance problems in React and the web platform.

Avatar for Matheus Albuquerque

Matheus Albuquerque PRO

May 10, 2026

More Decks by Matheus Albuquerque

Other Decks in Programming

Transcript

  1. Matheus Albuquerque ↝ 👨💻 STAFF SWE @ MEDALLIA ↝ ⚛

    CHAIR @ REACT SUMMIT NYC ↝ ⚡ GOOGLE DEVELOPER EXPERT ↝ 𝕏 YTHECOMBINATOR
  2. Which browsers are visiting our app? REACT: INTERNALS AND ADVANCED

    PERFORMANCE PATTERNS — APP DYNAMICS REPORT • 2022
  3. 40% of Brits reported that they had become physically violent

    toward their computers. — British Psychology Society • 2009 FRUSTRATION → STRESS
  4. Brainwave analysis from the experiment revealed that participants had to

    concentrate up to 50% more when using websites via the slower connection. — Study conducted by Foviance on behalf of CA • 2011 FRUSTRATION → STRESS
  5. Delayed web pages caused a 38% rise in mobile users'

    heart rates—equivalent to the anxiety of watching a horror movie alone. — Ericsson ConsumerLab • 2015 FRUSTRATION → ANXIETY
  6. “[…] With React you can build applications without even thinking

    about performance and the default state is fast.” — Rethinking Best Practices • Pete Hunt, 2013
  7. ↝ HOW QUICKLY A PAGE CAN LOAD AND RENDER ALL

    OF ITS VISUAL ELEMENTS TO THE SCREEN? ↝ HOW QUICKLY A PAGE CAN LOAD AND RUN ANY REQUIRED JAVASCRIPT IN ORDER FOR COMPONENTS TO RESPOND TO USER INTERACTION? ↝ DO TRANSITIONS AND ANIMATIONS RENDER AT A CONSISTENT FRAME RATE AND FLOW FLUIDLY? WHAT DOES IT MEAN TO BE FAST?
  8. PERF MITIGATORS: ↝ shouldComponentUpdate • React.PureComponent ↝ React.memo ↝ useMemo

    • useCallback ↝ useTransition • useDeferredValue • React.Suspense & MUCH MORE! MAKING THINGS “FAST”
  9. […] “While browsing HackerNews, I sometimes get the feeling that

    every developer out there is working for FAANG, as there are always posts from those people doing some hyped stu f . Or you might think that PHP is never used nowadays because whenever it’s mentioned, everyone is hating on it in the comments.” […] — The silent majority • Vadim Kravcenko, 2022
  10. […] “But let’s be straight, that’s like 1% of all

    of the developers out there — the rest of them are just lurking and coding with their language of choice and being content with it. Be it Fortran, COBOL, Perl, or PHP.” […] — The silent majority • Vadim Kravcenko, 2022
  11. ↝ POPULAR REACT HOOKS • (META) FRAMEWORKS. ↝ FINE-GRAINED REACTIVITY

    AND SIGNALS. ↝ RESUMABILITY AND NON-REACT RENDERING PATTERNS. WE’LL NOT FOCUS ON…
  12. METHODOLOGY: APP HOLOTYPES Portfolio Content Storefront Social Network I m

    m ersive Holotype Personal Blog CNN Amazon Facebook Figma Interactivity Minimal Linked Articles Purchase Multi-Point, Real-time Everything Session Depth Shallow Shallow Shallow - Medium Extended Deep Values Simplicity Discover-ability Load Performance Dynamicism I m m ersiveness Routing Server Server, HTML Swap HTML Swap, Hybrid Hybrid, Client Client Rendering Static Static, SSR Static, SSR SSR CSR Hydration None Progressive, Partial Partial, Resumable Any None (CSR) Frameworks 11ty Astro, Elder Marko, Qwik, Hydrogen Next, Remix Create React App — PATTERNS FOR BUILDING JAVASCRIPT WEBSITES IN 2022 • RYAN CARNIATO
  13. ↝ REVISITING COMPUTER SCIENCE CONCEPTS. ↝ UNDERSTANDING HOW TOOLS WORK

    UNDER THE HOOD AND THE RATIONALES BEHIND THEM BY CHECKING THEIR SOURCE CODE. ↝ LEVERAGING REAL-WORLD CASE STUDIES FROM SMALL, MEDIUM, AND ENTERPRISE-SCALE COMPANIES. ↝ MICRO EXPERIMENTS AND THEIR RESULTS. METHODOLOGY
  14. This workshop is designed to empower you with the knowledge

    and tools needed to tackle a variety of complex React and front-end performance challenges in your personal and professional projects. Also, it’s meant to bridge the gap between foundational computer science concepts and practical front-end development. — React: Internals and Advanced Performance Patterns • Matheus, 2026
  15. ↝ SCHEDULING THINGS ↝ RENDERING THINGS ↝ PREDICTING & PRIORITIZING

    THINGS ↝ COMPILING THINGS ↝ MEASURING THINGS ↝ THE FUTURE & CLOSING NOTES METHODOLOGY: TOPICS
  16. ↝ CLONING THE REPO NOW. ↝ GETTING THE SLIDES LATER.

    ↝ QUESTIONS AT THE END OF EACH SECTION. ↝ CONFERENCE BREAKS. METHODOLOGY: STEPS
  17. ↝ FIBERS • COROUTINES • EFFECT HANDLERS: OVERVIEW • REACT.JS

    • OTHER ECOSYSTEMS ↝ SCHEDULING: LONG TASKS • RUNNING STRATEGIES ↝ SCHEDULING IN REACT: OVERVIEW • HEURISTICS • PRIORITY LEVELS • RENDER LANES • USE CASES ↝ SCHEDULING ON THE WEB: OVERVIEW • NATIVE SCHEDULING API THIS SECTION PRESENTS…
  18. STACK FRAMES let frame: Frame = { return: frame, fn:

    add, parameters: [2, 2], localVariables: { result: 4, }, } function add(x,y) { const result = x + y; return result; } add(2, 2)
  19. STACK FRAMES let frame: Frame = { return: frame, fn:

    add, parameters: [2, 2], localVariables: { result: 4, }, } let fiber: Fiber = { return: fiber, component: Avatar, props: { id: 4 }, state: { isLoaded: true, }, }
  20. FIBERS ↝ FIBER ARCHITECTURE: REACT-SPECIFIC IMPLEMENTATION OF A CALL-STACK-LIKE MODEL

    WHERE REACT HAS FULL CONTROL OF SCHEDULING WHAT SHOULD BE DONE. ↝ FIBER: A STACK FRAME FOR A REACT COMPONENT.
  21. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES.
  22. UNITS OF WORK DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT

    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
  23. UNITS OF WORK DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT

    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  24. UNITS OF WORK DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT

    RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES.
  25. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE

    RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. ONCE A TEMPLATE GOES THROUGH THE JSX COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. AND THAT MAKES IT A CONVENIENT WAY TO TRACK, SCHEDULE, PAUSE AND ABORT THE WORK. UNITS OF WORK
  26. “Homoiconicity is a property of some programming languages in which

    the code used to express a program is written using the data structures of that language.” — Wikipedia
  27. HOMOICONICITY (let [x 1] (inc x)) ; = > 2

    PERFORMS A TEMPORARY BINDING (BINDS X TO THE VALUE 1)
  28. HOMOICONICITY (let [x 1] (inc x)) ; = > 2

    INCREMENTS X TO GIVE THE RETURN VALUE OF 2
  29. HOMOICONICITY IT CAN BE THOUGHT OF AS A LIST WITH

    THREE ELEMENTS: ↝ A SYMBOL NAMED LET ↝ A VECTOR WITH TWO ELEMENTS ↝ A LIST WITH TWO ELEMENTS
  30. HOMOICONICITY IT CAN BE THOUGHT OF AS A LIST WITH

    THREE ELEMENTS: ↝ A SYMBOL NAMED LET ↝ A VECTOR WITH TWO ELEMENTS ↝ A LIST WITH TWO ELEMENTS A SYMBOL (X) AND AN INTEGER A SYMBOL (INC) AND A SYMBOL (X)
  31. ↝ REACT ELEMENTS ARE JUST DATA. ↝ JUST LIKE IN

    LISP, REACT COMPONENTS CAN MANIPULATE THEIR CHILDREN AND RETURN COMPLETELY DIFFERENT THINGS. HOMOICONICITY + REACT
  32. “[…] Pattern matching consists of specifying patterns to which some

    data should conform and then checking to see if it does and deconstructing the data according to those patterns.” — Learn You a Haskell
  33. PATTERN MATCHING factorial : : (Integral a) = > a

    - > a factorial 0 = 1 factorial n = n * factorial (n - 1)
  34. PATTERN MATCHING fib : : (Integral a) = > a

    - > a fib 0 = 1 fib 1 = 1 fib n | n > = 2 = fib (n-1) + fib (n-2) factorial > factorial 0 = factorial n =
  35. PATTERN MATCHING / / . . . export function isWhen<Shape

    extends {}>( child: ElementWithMetadataUnion<Shape> ): child is ElementWithMetadata<WhenProps<Shape > > { return child.element.type === When; } / / . . . export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) = > ({ element: element, position: idx, })) as Array<ElementWithMetadata<Shape > > ; } / / . . .
  36. PATTERN MATCHING / / . . . export function isWhen<Shape

    extends {}>( child: ElementWithMetadataUnion<Shape> ): child is ElementWithMetadata<WhenProps<Shape > > { return child.element.type === When; } / / . . . export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) = > ({ element: element, position: idx, })) as Array<ElementWithMetadata<Shape > > ; } / / . . .
  37. PATTERN MATCHING const supportsSensor = () = > Boolean(window.AmbientLightSensor); const

    AmbientLight = React.lazy(() = > import("./AmbientLight")); const Fallback = React.lazy(() = > import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } = usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); }
  38. PATTERN MATCHING const supportsSensor = () = > Boolean(window.AmbientLightSensor); const

    AmbientLight = React.lazy(() = > import("./AmbientLight")); const Fallback = React.lazy(() = > import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } = usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); } PATTERN MATCHING + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY THE COMPONENT BUNDLE THAT MATCHES.
  39. PATTERN MATCHING const supportsSensor = () = > Boolean(window.AmbientLightSensor); const

    AmbientLight = React.lazy(() = > import("./AmbientLight")); const Fallback = React.lazy(() = > import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } = usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); } PATTERN MATCHING + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY THE COMPONENT BUNDLE THAT MATCHES. MANIPULATING BASED ON ELEMENTS DATA.
  40. USING FIBERS, REACT CAN: ↝ PAUSE, RESUME, AND RESTART RENDERING

    WORK ON COMPONENTS AS NEW UPDATES COME IN. ↝ REUSE PREVIOUSLY COMPLETED WORK. ↝ SPLIT WORK INTO CHUNKS AND PRIORITIZE TASKS BASED ON IMPORTANCE. FIBERS IN REACT: RECAP
  41. ↝ ASYNCHRONICITY IN JAVASCRIPT IS CONTAGIOUS. ↝ IF ANY FUNCTION

    IS ASYNC, THEN EVERYTHING THAT CALLS IT MUST ALSO BE ASYNC… ↝ …AND SO ON UNTIL THE ENTIRE PROGRAM IS ASYNCHRONOUS. ASYNCHRONICITY IN JAVASCRIPT
  42. ↝ ASYNCHRONICITY IN JAVASCRIPT ISN’T FREE. ↝ EVERY ASYNC FUNCTION

    CALL HAS TO: ↝ ALLOCATE CALLBACKS & STORE THEM SOMEWHERE. ↝ TAKE A TRIP BACK TO THE EVENT LOOP BEFORE INVOKING THOSE CALLBACKS. ASYNCHRONICITY IN JAVASCRIPT
  43. ↝ ITS API HAS TWO MAIN FUNCTIONS FOR COMPILING SASS

    FILES: ONE SYNC AND ONE ASYNC. ↝ THE ASYNC ONE BECAME WIDELY USED IN PRACTICE BECAUSE IT ENABLED ASYNC PLUGINS (E.G. WEBPACK’S SASS-LOADER). ASYNCHRONICITY & SASS
  44. ↝ FOR NODE SASS, THE PERFORMANCE DIFFERENCE WAS NEGLIGIBLE, BECAUSE

    IT WAS BUILT ON C++. ↝ HOWEVER, DART SASS RUNS AS PURE JAVASCRIPT, WHICH MAKES IT SUBJECT TO JAVASCRIPT’S ASYNCHRONICITY RULES. ASYNCHRONICITY & SASS
  45. ↝ THE ASYNC VERSION IN DART SASS WAS 2-3X SLOWER

    THAN THE SYNC ONE. ↝ THEY STARTED USING NODE-FIBERS TO IMPLEMENT THE ASYNC API USING THE FAST, SYNC, CODE. ASYNCHRONICITY & SASS
  46. ↝ A FIBER IS A LIGHTWEIGHT, COOPERATIVE, CONCURRENT EXECUTION UNIT.

    ↝ FIBERS ARE A COMMON RESOURCE IN SOME OPERATING SYSTEMS AND IN SOME PROGRAMMING LANGUAGES. ↝ RUNTIMES USUALLY INCLUDE A SCHEDULER THAT SCHEDULES THE EXECUTION OF FIBERS. FIBERS OUT THERE
  47. “This attitude does not only work in the context of

    the game industry, though. Any other industry with strong architectural requirements can be a source of inspiration and knowledge for us and help us write better code on the web” An Actor, a model and an architect walk onto the web... • Surma
  48. COROUTINES IN REACT THE IDEA BEHIND COROUTINES — AS OPPOSED TO FIBERS — WAS

    TO GIVE COMPONENTS EXPLICIT CONTROL OVER YIELDING AND RESUMPTION. COROUTINES APPEARED WHEN WORK ON FIBER WAS FIRST GOING AS A SPECIFIC COMPONENT TYPE.
  49. COROUTINES VS. FIBERS FIBERS CONTROL IS PASSED TO A SCHEDULER

    WHICH DETERMINES WHAT TO RUN NEXT. COROUTINES CONTROL IS PASSED TO THE CALLER AND HANDLED BY APPLICATION CODE.
  50. COROUTINES VS. FIBERS ↝ BOTH DECIDE WHEN TO DROP CONTROL

    (AKA. YIELD). ↝ COROUTINES CAN BE USED TO IMPLEMENT FIBERS BY ALWAYS YIELDING TO A SCHEDULER COROUTINE. ↝ FIBERS CAN BE USED TO IMPLEMENT COROUTINES BY ALLOWING EACH FIBER TO COMMUNICATE TO THE SCHEDULER WHICH FIBER SHOULD BE RUN WHEN IT YIELDS.
  51. EFFECT HANDLERS APPROACH TO REASONING ABOUT COMPUTATIONAL EFFECTS IN PURE

    CONTEXTS. ↝ EFFECT: A SET OF OPERATIONS. ↝ EFFECT HANDLER: RESPONSIBLE FOR HANDLING THE SEMANTICS OF HOW TO IMPLEMENT EFFECTS.
  52. EFFECT HANDLERS: EFF (* state.eff *) type user = string

    * int effect Get: user effect Set: user - > unit
  53. EFFECT HANDLERS: EFF (* state.eff *) type user = string

    * int effect Get: user effect Set: user - > unit A USER WITH A NAME AND AGE.
  54. EFFECT HANDLERS: EFF (* state.eff *) type user = string

    * int effect Get: user effect Set: user - > unit WE DEFINE EFFECTS WITH THE effect KEYWORD AND A TYPE SIGNATURE.
  55. EFFECT HANDLERS: EFF let state = handler | y -

    > fun currentState - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;;
  56. EFFECT HANDLERS: EFF let state = handler | y -

    > fun currentState - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; WE HAVE A handler WITH THREE BRANCHES, AND ALL OF THEM RETURN A FUNCTION.
  57. EFFECT HANDLERS: EFF let state = handler | y -

    > fun currentState - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; NO EFFECT (WHEN WE REACH THE END OF THE BLOCK). y IS THE RETURN VALUE.
  58. EFFECT HANDLERS: EFF let state = handler | y -

    > fun currentState - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; MATCHING OUR EFFECTS.
  59. let state = handler | y - > fun currentState

    - > (y, currentState) | effect Get k - > (fun currentState - > (continue k currentState) currentState) | effect (Set newState) k - > (fun _ - > (continue k ()) newState) ;; EFFECT HANDLERS: EFF k IS A CONTINUATION. IT REPRESENTS THE REST OF THE COMPUTATION AFTER WHERE WE PERFORM AN EFFECT.
  60. function getName(user) { let name = user.name; if (name ===

    null) { name = perform 'ask_name'; } return name; } const arya = { name: null, friendNames: [] }; const gendry = { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { if (effect === 'ask_name') { resume with 'Arya Stark'; } }
  61. function getName(user) { let name = user.name; if (name ===

    null) { name = perform 'ask_name'; } return name; } const arya = { name: null, friendNames: [] }; const gendry = { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { if (effect === 'ask_name') { resume with 'Arya Stark'; } }
  62. function getName(user) { let name = user.name; if (name ===

    null) { name = perform 'ask_name'; } return name; } const arya = { name: null, friendNames: [] }; const gendry = { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { if (effect === 'ask_name') { resume with 'Arya Stark'; } } THROW → PERFORM CATCH → HANDLE LETS US JUMP BACK TO WHERE WE PERFORMED THE EFFECT.
  63. EFFECT HANDLERS ↝ IT DOESN'T REALLY MATTER HOW WE HOLD

    STATE. ↝ WITH PROMISES, IF WE WERE TO CHANGE IN THE FUTURE, THAT’D REQUIRE CHANGES ACROSS EVERYTHING. ↝ WITH ALGEBRAIC EFFECTS, WE CAN SIMPLY STOP THE CURRENT PROCESS ALTOGETHER UNTIL OUR EFFECTS ARE FINISHED.
  64. LAYOUT ALGORITHM THE REACT TEAM APPARENTLY SPENT SOME TIME EXPERIMENTING

    WITH EFFECT-HANDLER CONTROL STRUCTURES FOR MANAGING LAYOUT.
  65. #3 Side e ff ects within a component REACT: INTERNALS

    AND ADVANCED PERFORMANCE PATTERNS
  66. function ThemeBorderColorRequest() { } function FancyBox(children) { const color =

    raise new ThemeBorderColorRequest(); return { borderWidth: '1px', borderColor: color, children: children }; } function BlueTheme(children) { return try { children(); } catch effect ThemeBorderColorRequest - > [, continuation] { continuation('blue'); } } function App(data) { return BlueTheme( FancyUserList.bind(null, data.users) ); }
  67. function ThemeBorderColorRequest() { } function FancyBox(children) { const color =

    raise new ThemeBorderColorRequest(); return { borderWidth: '1px', borderColor: color, children: children }; } function BlueTheme(children) { return try { children(); } catch effect ThemeBorderColorRequest - > [, continuation] { continuation('blue'); } } function App(data) { return BlueTheme( FancyUserList.bind(null, data.users) ); } THROW → RAISE CATCH → CATCH EFFECT
  68. HOOKS API ↝ ALGEBRAIC EFFECTS = A SET OF OPERATIONS

    AND A SET OF EFFECT HANDLERS. ↝ THE OPERATIONS HERE ARE OUR HOOKS (E.G. useState, useEffect, AND SO ON). ↝ WE HAVE TO SET UP HANDLERS IN EFF; IN REACT THEY'RE SET UP AS PART OF THE RENDER CYCLE.
  69. HOOKS API ↝ REACT IS RESPONSIBLE FOR MUCH OF THE

    IMPLEMENTATION OF WHEN/HOW OUR EFFECTS RUN. ↝ BY SPLITTING EFFECTS AND RENDERING, WE ALLOW IT TO RELIEVE US OF SOME COMPLEXITY.
  70. SUSPENSE INTERNALS A COMPONENT IS ABLE TO SUSPEND THE FIBER

    IT IS RUNNING IN BY THROWING A PROMISE, WHICH IS CAUGHT AND HANDLED BY THE FRAMEWORK.
  71. SUSPENSE INTERNALS A COMPONENT IS ABLE TO SUSPEND THE FIBER

    IT IS RUNNING IN BY THROWING A PROMISE, WHICH IS CAUGHT AND HANDLED BY THE FRAMEWORK. THROW → HANDLE → RESUME PATTERN.
  72. TASKS A UNIT OF WORK THAT THE BROWSER DOES TO

    RENDER A FRAME. JAVASCRIPT STYLES LAYOUT PAINT COMPOSITE
  73. LONG TASKS ↝ IF A TASK TAKES MORE THAN 50

    MS, USER INPUT FEELS DELAYED. ↝ BASED ON THE USER-CENTRIC PERFORMANCE MODEL CALLED RAIL. ↝ THEY TAKE TOO LONG AND BLOCK OTHER TASKS.
  74. TASK RUNNING STRATEGIES ↝ PARALLELISM: MULTIPLE THREADS = MULTIPLE TASKS

    AT THE SAME TIME ON SEPARATE CPU CORES. ↝ CONCURRENCY: SINGLE THREAD + QUICKLY SWITCHING BETWEEN TASKS. ↝ SCHEDULING: CONCURRENCY + TASK PRIORITIZATION.
  75. WEB WORKERS ↝ DATA EXCHANGE IS THROUGH MESSAGE-PASSING. ↝ NO

    ACCESS TO ANY VARIABLES/CODE FROM THE PAGE THAT CREATED THEM OR VICE VERSA. ↝ NO ACCESS TO THE DOM, MAKING UI UPDATES FROM A WORKER BARELY IMPOSSIBLE. ↝ TWO MODELS: ACTORS & SHARED MEMORY.
  76. WEB WORKERS: ACTORS ↝ EACH ACTOR MAY OR MAY NOT

    RUN ON A SEPARATE THREAD AND FULLY OWNS THE DATA IT IS OPERATING ON. ↝ ACTORS CAN ONLY SEND/REACT TO MESSAGES. ↝ MAIN THREAD = ACTOR THAT OWNS THE DOM/UI.
  77. WEB WORKERS: ACTORS ↝ EVERY MESSAGE WE SEND NEEDS TO

    BE COPIED. ↝ BALANCE: MOVING CODE TO A WORKER VS COMMUNICATION OVERHEAD/WORKER BEING BUSY. ↝ postMessage IS A FIRE-AND-FORGET MESSAGING MECHANISM WITH NO BUILT-IN UNDERSTANDING OF REQUEST AND RESPONSE.
  78. WEB WORKERS: SHARED MEMORY ↝ ONE DEDICATED TYPE: SharedArrayBuffer. ↝

    A LINEAR CHUNK OF MEMORY THAT CAN BE MANIPULATED USING TypedArrays OR DataViews. ↝ IF SENT VIA postMessage, THE OTHER END GETS A HANDLE TO THE EXACT SAME MEMORY CHUNK.
  79. WEB WORKERS: SHARED MEMORY ↝ MOST OF THE APIS ARE

    BUILT NO CONCURRENT ACCESS TO OBJECTS IN MIND. ↝ YOU BUILD YOUR OWN MUTEX ABSTRACTIONS AND OTHER CONCURRENT DATA STRUCTURES. ↝ NO DIRECT WAY OF WORKING ON FAMILIAR OBJECTS/ ARRAYS; JUST A SERIES OF BYTES.
  80. WORKERS: WEB ASSEMBLY ↝ WORKERS + SharedArrayBuffers TO SUPPORT THE

    THREADING MODEL OF C++ AND OTHERS. ↝ THE BEST EXPERIENCE FOR SHARED-MEMORY MODEL. ↝ FASTER THAN JS WHEN YOU STAY WITHIN WASM, BUT THE MORE YOU HAVE TO CROSS OVER TO JS APIS THE SLOWER IT IS.
  81. WORKERS: WEB ASSEMBLY ↝ JAVASCRIPT IS OFTEN FASTER AT DOING

    DOM RENDERING. ↝ HIGH-LEVEL LIBRARIES CAN BE MORE PERFORMANT THAN LOW-LEVEL WASM IMPLEMENTATIONS. ↝ DOESN’T OFFER LOT OF THE BENEFITS (AND COMFORT) OF JAVASCRIPT.
  82. WORKERS ↝ GOOD FOR DATA PROCESSING AND CRUNCHING NUMBERS. ↝

    HARD TO USE FOR UI-RELATED STUFF. ↝ HARDER THAN ADJUSTING IT FOR A SCHEDULER.
  83. function* resourcefulOperation(value: number) { let newValue = String(value); while (true)

    { yield; for (let i = 0; i < 1000000; i++) { newValue = `${value} + ${i} = ${value + i}`; } return newValue; } } const initialValue = 0; const scheduler = new Scheduler(resourcefulOperation, initialValue); function ResourcefulComponent(props: { value: number }) { const { value } = props; const result = scheduler.performUnitOfWork(value); return <p>{result}</p>; } PROMOTED TO A GENERATOR YIELDING EXECUTION DOING CONCURRENT TASKS
  84. function resourcefulOperation(value: number) { let newValue = String(value); for (let

    i = 0; i < 1000000; i++) { newValue = `${value} + ${i} = ${value + i}`; } return newValue; } function ResourcefulComponent(props: { value: number }) { const { value } = props; const result = resourcefulOperation(value); return <p>{result}</p>; } SCHEDULING WITH… OUR SCHEDULER
  85. function resourcefulOperation(value: number) { let newValue = String(value); for (let

    i = 0; i < 1000000; i++) { newValue = `${value} + ${i} = ${value + i}`; } return newValue; } function ResourcefulComponent(props: { value: number }) { const [_, startTransition] = useTransition(); const [result, setResult] = useState(""); useEffect(() = > { startTransition(() = > { const newResult = resourcefulOperation(props.value); setResult(newResult); }); }, [props.value]); return <p>{result}</p>; } SCHEDULING WITH… OUR SCHEDULER
  86. HEURISTICS ↝ A COOPERATIVE MULTITASKING MODEL. ↝ A SINGLE INTERRUPTIBLE

    RENDERING THREAD. ↝ RENDERING CAN BE INTERLEAVED WITH OTHER MAIN THREAD TASKS AND OTHER REACT RENDERS. ↝ AN UPDATE CAN HAPPEN IN THE BACKGROUND WITHOUT BLOCKING THE RESPONSE TO NEW INPUT.
  87. HEURISTICS ↓ ORIGINAL RENDER TASK USER INPUT → ↑ HIGHER

    PRIORITY RENDER TASK ↓ RESUME ORIGINAL RENDER TASK
  88. HEURISTICS ↝ IT YIELDS EXECUTION IS BACK TO THE MAIN

    THREAD EVERY 5MS. ↝ IT'S SMALLER THAN A SINGLE FRAME EVEN ON 120FPS, SO IT WON'T BLOCK ANIMATIONS. ↝ IN PRACTICE, RENDERING IS INTERRUPTIBLE.
  89. PRIORITY LEVELS PRIORITY TIMEOUT WHEN I m m ediate SYNCHRONOUSLY

    TASKS THAT NEED TO RUN SYNCHRONOUSLY UserBlocking 250MS RESULTS OF A USER INTERACTION (E.G. A BUTTON CLICK) Normal 5S UPDATES THAT DON’T HAVE TO FEEL INSTANTANEOUS Low 10S TASKS THAT CAN BE DEFERRED BUT MUST STILL COMPLETE EVENTUALLY (E.G. AN ANALYTICS NOTIFICATION) Idle NO TIMEOUT TASKS THAT DO NOT HAVE TO RUN AT ALL (E.G. HIDDEN OFFSCREEN CONTENT)
  90. #research 📚 In a recent study of 918 adults, 77%

    agreed that Christmas seems to arrive more rapidly each year. Interestingly, co- researchers asked an Iraqi sample the same question about Ramadan and received a very similar response.
  91. TIME PERCEPTION: COMPUTERS IN 1968 — RESPONSE TIME IN MAN-COMPUTER

    CONVERSATIONAL TRANSACTIONS • ROBERT B. MILLER, 1968
  92. RENDER LANES ↝ ONE LANE: ONE BIT IN A BITMASK.

    ↝ ONE UPDATE IN REACT: ONE LANE. ↝ ONE RENDER IN REACT: ONE OR MORE LANES. ↝ UPDATES IN THE SAME LANE: RENDER IN THE SAME BATCH. ↝ DIFFERENT LANES: SEPARATE BATCHES.
  93. RENDER LANES ↝ 31 LEVELS OF GRANULARITY (= ONE BITMASK).

    ↝ ALLOWS TO CHOOSE WHETHER TO RENDER MULTIPLE TRANSITIONS IN A SINGLE BATCH OR RENDER THEM INDEPENDENTLY. ↝ REDUCES OVERHEAD OF MULTIPLE LAYOUT PASSES, STYLE RECALCULATIONS, AND MULTIPLE PAINTS.
  94. HANDLING LARGE SETS OF DATA 😊 PRACTICAL… 😔 NON-PRACTICAL… ↝

    FINDING PRIMES ↝ CRACKING PASSWORDS ↝ SIERPINSKI TRIANGLE ↝ RENDERING MANY DATA-POINTS ↝ PROCESSING DATA ↝ RENDERING ON A <canvas>
  95. HANDLING LARGE SETS OF DATA 😊 PRACTICAL… 😔 NON-PRACTICAL… ↝

    FINDING PRIMES ↝ CRACKING PASSWORDS ↝ SIERPINSKI TRIANGLE ↝ RENDERING MANY DATA-POINTS ↝ PROCESSING DATA ↝ RENDERING ON A <canvas>
  96. ↝ ˜100K DATA POINTS PLOTTED ↝ SUPPORT FOR SEARCHING AND

    FILTERING. ↝ USED WORKERS + REDUX-SAGA UTILITIES + DEBOUNCING. ↝ COULD'VE USED TRANSITIONS. #1 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS LOCATION DATA
  97. ↝ THOUSANDS OF REAL-TIME PLAYERS MESSAGING. ↝ SUPPORT FOR SEARCHING

    AND FILTERING. ↝ USED VIRTUALIZATION AND MEMOIZATION. ↝ COULD'VE USED TRANSITIONS. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS GAME ADMIN PANEL #2
  98. useSyncExternalStore function useSyncExternalStore<Snapshot>( subscribe: (onStoreChange: () = > void) =

    > () = > void, getSnapshot: () = > Snapshot, getServerSnapshot?: () = > Snapshot ): Snapshot;
  99. useLocation function Pathname() { const { pathname } = useLocation();

    return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const { hash } = useLocation(); return <Badge title={hash} subtitle="hash" />; }
  100. useLocation function Pathname() { const { pathname } = useLocation();

    return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const { hash } = useLocation(); return <Badge title={hash} subtitle="hash" />; }
  101. useHistorySelector function useHistorySelector(selector) { const history = useHistory(); return useSyncExternalStore(history.listen,

    () = > selector(history)); } function Pathname() { const pathname = useHistorySelector((history) = > history.location.pathname); return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const hash = useHistorySelector((history) = > history.location.hash); return <Badge title={hash} subtitle="hash" />; }
  102. useHistorySelector function useHistorySelector(selector) { const history = useHistory(); return useSyncExternalStore(history.listen,

    () = > selector(history)); } function Pathname() { const pathname = useHistorySelector((history) = > history.location.pathname); return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const hash = useHistorySelector((history) = > history.location.hash); return <Badge title={hash} subtitle="hash" />; }
  103. …AND MUCH MORE! function subscribe(callback) { window.addEventListener('online', callback); window.addEventListener('offline', callback);

    return () = > { window.removeEventListener('online', callback); window.removeEventListener('offline', callback); }; } function getSnapshot() { return navigator.onLine; }
  104. …AND MUCH MORE! import { useSyncExternalStore } from 'react'; function

    OnlineStatus() { const isOnline = useSyncExternalStore( subscribe, getSnapshot, getSnapshot ); return ( <div className={isOnline ? 'online' : 'offline'}> {isOnline ? '🟢 Online' : '🔴 Offline'} </div> ); }
  105. ↝ NO PRIORITY CONTROL. ↝ NO CANCELLATION SEMANTICS. ↝ NO

    COORDINATION WITH THE BROWSER SCHEDULER. ↝ NO INPUT RESPONSIVENESS GUARANTEES. ↝ NO WAY TO BREAK LONG TASKS SAFELY. NATIVE SCHEDULING: CURRENT ISSUES
  106. ↝ SCHEDULE TASKS WITH EXPLICIT PRIORITY. ↝ COORDINATE WITH THE

    BROWSER RENDERING PIPELINE. ↝ REPLACE setTimeout( . . . , 0) HACKS. ↝ SUPPORTS CANCELLATION VIA SIGNALS. ↝ WORKS IN WORKERS TOO. SCHEDULE TASKS: OVERVIEW
  107. ↝ SPLIT LONG TASKS SAFELY. ↝ RETURN CONTROL TO THE

    BROWSER MID-EXECUTION. ↝ CONTINUE LATER WITH THE SAME PRIORITY. ↝ AVOID BLOCKING INPUT AND RENDERING. ↝ REPLACE MANUAL CHUNKING LOOPS. YIELDING: OVERVIEW
  108. PENDING INPUT: OVERVIEW while (workQueue.length > 0) { if (navigator.scheduling.isInputPending())

    { / / Stop doing work to handle any input event break; } let job = workQueue.shift(); job.execute(); }
  109. Hydration is the process of attaching behavior to declarative content

    to make it interactive. — Why Progressive Hydration is Harder than You Think • Miško Hevery
  110. ↝ ASSOCIATE DOM ELEMENTS WITH THEIR CORRESPONDING EVENT HANDLERS. ↝

    ONCE A USER EVENT TRIGGERS A HANDLER, WE NEED TO UPDATE THE STATE. ↝ ONCE THE STATE UPDATES, THE FRAMEWORK NEEDS TO RECREATE THE COMPONENT HIERARCHY. HYDRATION: INNER CHALLENGES
  111. HYDRATION: UX CHALLENGES GET HTML DOWNLOAD JS PARSE + EXECUTE

    JS RECOVER STATE + BIND LISTENERS 🟢 FAST (USUALLY)
  112. HYDRATION: UX CHALLENGES GET HTML DOWNLOAD JS PARSE + EXECUTE

    JS RECOVER STATE + BIND LISTENERS 🔴 SLOW (ON BAD NETWORK CONDITIONS)
  113. HYDRATION: UX CHALLENGES GET HTML DOWNLOAD JS PARSE + EXECUTE

    JS RECOVER STATE + BIND LISTENERS 🔴 SLOW (DEPENDING ON THE DEVICE AND AMOUNT OF JAVASCRIPT)
  114. HYDRATION: UX CHALLENGES RECOVER STATE + BIND LISTENERS 🔴 SLOW

    (DEPENDING ON THE AMOUNT OF DOM NODES TO BE TRAVERSED AND REFERENCES TO BE RE-BOUND TO LISTENERS) GET HTML DOWNLOAD JS PARSE + EXECUTE JS
  115. ↝ DO WE SEND ALL JS ON EVERY REQUEST? OR

    DO WE BASE IT ON THE ROUTE? ↝ IS HYDRATION DONE TOP-DOWN? AND HOW EXPENSIVE IS THAT? ↝ HOW DOES THE DEVELOPER ORGANIZE THE CODE BASE? HYDRATION: DX CHALLENGES
  116. HYDRATION: SOLUTIONS HYDRATION COMPONENT 1 COMPONENT 2 COMPONENT 3 PARTIAL

    HYDRATION (WHAT) COMPONENT 3 COMPONENT 2 COMPONENT 1
  117. HYDRATION: SOLUTIONS PARTIAL HYDRATION (WHAT) COMPONENT 3 COMPONENT 2 COMPONENT

    1 PROGRESSIVE HYDRATION (WHEN) COMPONENT 3 COMPONENT 2 COMPONENT 1
  118. Islands are a component-based architecture that suggests a compartmentalized view

    of the page with static and dynamic islands. — Islands Architecture • patterns.dev
  119. ↝ SELECTIVELY, PROGRESSIVELY ENHANCING BITS OF SERVER-RENDERED HTML WITH CLIENT-SIDE

    JS. ↝ SMALL, FOCUSED, CHUNKS OF INTERACTIVITY WITHIN SERVER-RENDERED WEB PAGES. ↝ SINGLE APPLICATION IN CONTROL OF FULL-PAGE RENDERING → MULTIPLE ENTRY POINTS. ISLANDS ARCHITECTURE
  120. ↝ THE SCRIPT FOR THE ISLANDS CAN BE DELIVERED AND

    HYDRATED INDEPENDENTLY, ALLOWING THE REST OF THE PAGE TO BE JUST STATIC HTML. ↝ COMPARED TO PROGRESSIVE ENHANCEMENT, THERE’S MORE SPECIFICITY AROUND HOW THE ENHANCEMENT OCCURS. ISLANDS ARCHITECTURE
  121. HYDRATION vs. ISLANDS POST TITLE POST CONTENT COMMENTS SOCIAL CTA

    POST TITLE POST CONTENT COMMENTS SOCIAL CTA POST TITLE (STATIC HTML) POST CONTENT (STATIC HTML) COMMENTS SOCIAL CTA RENDER ALL COMPONENTS TOGETHER AND HYDRATE. RENDER ALL COMPONENTS, HYDRATE KEY ONES FIRST AND THEN PROGRESSIVELY HYDRATE THE OTHERS. STATIC COMPONENTS ARE SERVER-RENDERED HTML. SCRIPTS ARE REQUIRED ONLY FOR INTERACTIVE ONES. TRADITIONAL HYDRATION PROGRESSIVE HYDRATION ISLANDS
  122. HYDRATION vs. ISLANDS POST TITLE POST CONTENT COMMENTS SOCIAL CTA

    POST TITLE POST CONTENT COMMENTS SOCIAL CTA POST TITLE (STATIC HTML) POST CONTENT (STATIC HTML) COMMENTS SOCIAL CTA RENDER ALL COMPONENTS TOGETHER AND HYDRATE. RENDER ALL COMPONENTS, HYDRATE KEY ONES FIRST AND THEN PROGRESSIVELY HYDRATE THE OTHERS. STATIC COMPONENTS ARE SERVER-RENDERED HTML. SCRIPTS ARE REQUIRED ONLY FOR INTERACTIVE ONES. TRADITIONAL HYDRATION PROGRESSIVE HYDRATION ISLANDS
  123. HYDRATION vs. ISLANDS POST TITLE POST CONTENT COMMENTS SOCIAL CTA

    POST TITLE POST CONTENT COMMENTS SOCIAL CTA POST TITLE (STATIC HTML) POST CONTENT (STATIC HTML) COMMENTS SOCIAL CTA RENDER ALL COMPONENTS TOGETHER AND HYDRATE. RENDER ALL COMPONENTS, HYDRATE KEY ONES FIRST AND THEN PROGRESSIVELY HYDRATE THE OTHERS. STATIC COMPONENTS ARE SERVER-RENDERED HTML. SCRIPTS ARE REQUIRED ONLY FOR INTERACTIVE ONES. TRADITIONAL HYDRATION PROGRESSIVE HYDRATION ISLANDS
  124. ISLANDS ARCHITECTURE PAGE LAYOUT (SSR’D) POST TITLE (SSR'D) POST CONTENT

    (SSR’D) COMMENTS PLACEHOLDER (SSR) SOCIAL CTA PLACEHOLDER (SSR) COMMENTS “APP” (SSR’D + HYDRATION SCRIPT) SOCIAL CTA “APP” (SSR’D + HYDRATION SCRIPT)
  125. ISLANDS ARCHITECTURE PAGE LAYOUT (SSR’D) POST TITLE (SSR'D) POST CONTENT

    (SSR’D) COMMENTS PLACEHOLDER (SSR’D) SOCIAL CTA PLACEHOLDER (SSR’D) COMMENTS “APP” (SSR’D + HYDRATION SCRIPT) SOCIAL CTA “APP” (SSR’D + HYDRATION SCRIPT)
  126. ↝ STANDALONE: Astro, Qwik, Marko, Iles, Capri ↝ PREACT: Fresh,

    preact-island, microsite ↝ SOLIDJS: Solid Start, isolid ↝ SVELTE: Elder.js ISLANDS ARCHITECTURE
  127. ↝ STREAMING RENDERING + AUTOMATIC PARTIAL HYDRATION + COMPILER. ↝

    AUTOMATIC PARTIAL HYDRATION ALLOWS INTERACTIVE COMPONENTS TO HYDRATE THEMSELVES. ↝ HYDRATION CODE IS ONLY SHIPPED FOR INTERACTIVE COMPONENTS. ISLANDS ARCHITECTURE
  128. ↝ BY DEFAULT, SHIPS ZERO JAVASCRIPT. ↝ EVERY ISLAND IS

    LOADED IN PARALLEL. ↝ MULTI-FRAMEWORK: BUILD ISLANDS WITH REACT, PREACT, SVELTE, VUE, AND OTHERS. ↝ YOU CAN SPECIFY THE LOADING STRATEGY FOR EACH ISLAND INDIVIDUALLY. ISLANDS ARCHITECTURE: ASTRO
  129. ISLANDS ARCHITECTURE: ASTRO - - - import MyReactComponent from '

    . . /components/MyReactComponent.jsx'; - - - <MyReactComponent />
  130. ISLANDS ARCHITECTURE: ASTRO - - - import MyReactComponent from '

    . . /components/MyReactComponent.jsx'; - - - <MyComponent client:load /> <MyComponent client:idle /> <MyComponent client:visible /> <MyComponent client:media={string} /> <MyComponent client:only={string} />
  131. ISLANDS ARCHITECTURE: ASTRO - - - import MyReactComponent from '

    . . /components/MyReactComponent.jsx'; - - - <MyComponent client:media="(max-width: 20em)" /> <MyComponent client:idle={{timeout: 200}} /> <MyComponent client:visible={{rootMargin: "200px"}} />
  132. ISLANDS ARCHITECTURE: ASTRO - - - import MyReactComponent from '

    . . /components/MyReactComponent.jsx'; - - - <MyComponent client:media="(max-width: 20em)" /> <MyComponent client:idle={{timeout: 200}} /> <MyComponent client:visible={{rootMargin: "200px"}} />
  133. ISLANDS ARCHITECTURE: ASTRO - - - import MyReactComponent from '

    . . /components/MyReactComponent.jsx'; - - - <MyComponent client:media="(max-width: 20em)" /> <MyComponent client:idle={{timeout: 200}} /> <MyComponent client:visible={{rootMargin: "200px"}} />
  134. #idea💡 An e-commerce. Product pages have static descriptions and links.

    Interactive components (e.g., image carousels, search bar) are available in di ff erent regions.
  135. #idea💡 An internet banking app. The account details page contains

    a list of static transactions with fi lters providing some interactivity.
  136. ISLANDS ARCHITECTURE: ASTRO 🟢 REDUCES THE AMOUNT OF JAVASCRIPT CODE

    SHIPPED TO THE CLIENT 🟢 FASTER PAGE LOADS AND TIME TO INTERACTIVE (TTI) 🟢 KEY CONTENT IS AVAILABLE ALMOST IMMEDIATELY TO THE USER 🟢 STATIC CONTENT IS RENDERED ON THE SERVER = PAGES ARE SEO-FRIENDLY GREAT 🟡 HIGHLY INTERACTIVE PAGES WOULD PROBABLY REQUIRE THOUSANDS OF ISLANDS NOT GREAT
  137. ISLANDS ARCHITECTURE: ASTRO 🟢 REDUCES THE AMOUNT OF JAVASCRIPT CODE

    SHIPPED TO THE CLIENT 🟢 FASTER PAGE LOADS AND TIME TO INTERACTIVE (TTI) 🟢 KEY CONTENT IS AVAILABLE ALMOST IMMEDIATELY TO THE USER 🟢 STATIC CONTENT IS RENDERED ON THE SERVER = PAGES ARE SEO-FRIENDLY GREAT 🟡 HIGHLY INTERACTIVE PAGES WOULD PROBABLY REQUIRE THOUSANDS OF ISLANDS NOT GREAT
  138. ↝ HYDRATION COULD ONLY BEGIN AFTER THE ENTIRE DATA WAS

    FETCHED AND RENDERED. ↝ USERS COULDN’T INTERACT WITH THE PAGE UNTIL HYDRATION WAS COMPLETE FOR THE WHOLE PAGE. ↝ PARTS OF YOUR APP THAT LOAD FAST WOULD ALWAYS HAVE TO WAIT FOR THE SLOW ONES. HYDRATION IN REACT: BEFORE
  139. HYDRATION IN REACT: BEFORE FETCHING DATA (SERVER) RENDERING HTML (SERVER)

    LOADING CODE (CLIENT) HYDRATING TIME TO FIRST BYTE FIRST CONTENTFUL PAINT TIME TO INTERACTIVE
  140. HYDRATION IN REACT: AFTER TIME TO FIRST BYTE FIRST CONTENTFUL

    PAINT TIME TO INTERACTIVE […] FETCHING DATA (SERVER) RENDERING HTML (SERVER) HYDRATING LOADING CODE (CLIENT) […] […] […] […] […] […]
  141. ↝ REACT PRIORITIZES HYDRATING THE PARTS THAT THE USER INTERACTED

    WITH BEFORE THE REST. ↝ COMPONENTS CAN BECOME INTERACTIVE FASTER BY ALLOWING THE BROWSER TO DO OTHER WORK AT THE SAME TIME AS HYDRATION. HYDRATION IN REACT: AFTER
  142. ↝ REACT WON'T WAIT FOR HUGE COMPONENTS TO LOAD TO

    CONTINUE STREAMING HTML FOR THE REST OF THE PAGE. ↝ WHEN THE HTML BECOMES AVAILABLE ON THE SERVER, IT WILL BE ADDED TO THE SAME STREAM ALONG WITH A SCRIPT TAG AND INSERTED IN THE RIGHT PLACE. HYDRATION IN REACT: AFTER
  143. ↝ COMPONENTS THAT RUN EXCLUSIVELY ON THE SERVER. ↝ THEY

    RENDER ONCE ON THE SERVER TO GENERATE UI. THEY NEVER HYDRATE OR RE-RENDER. ↝ THEIR CODE ISN'T INCLUDED IN THE JS BUNDLE. ↝ THE RENDERED OUTPUT IS SENT TO THE CLIENT AND REMAINS IMMUTABLE. RSC: SERVER COMPONENTS
  144. ↝ THE CLASSIC COMPONENTS WE KNOW ARE NOW CLIENT COMPONENTS.

    ↝ AHEAD-OF-TIME REACT RENDERING (DURING THE BUILD OR ON THE SERVER). ↝ A ROUTING PARADIGM INTEGRATED WITH DATA FETCHING AND BUNDLING. ↝ UNRELATED TO SSR AND HYDRATION. RSC: SERVER COMPONENTS
  145. ↝ ALMOST IDENTICAL TO HOW ISLANDS WORK. ↝ “use client”

    MARKS A BOUNDARY BETWEEN TWO MODULE GRAPHS. ↝ EACH COMPONENT DECIDES WHETHER TO BE A SERVER COMPONENT OR TO STICK WITH BEING A SERVER + CLIENT COMPONENT. RSC: PARADIGM
  146. RSC: CLIENT COMPONENTS 'use client'; import React from 'react'; function

    Counter() { const [count, setCount] = React.useState(0); return ( <button onClick={() = > setCount(count + 1)}> Current value: {count} </button> ); } export default Counter;
  147. RSC: BOUNDARIES APP HEADER PAGE LAYOUT POST POST TITLE POST

    CONTENT 'use client' COMMENTS 'use client' SOCIAL CTA
  148. ↝ THE CODE FOR SERVER COMPONENTS IS NEVER DELIVERED TO

    THE CLIENT. ↝ ACCESS TO THE BACK-END FROM THE TREE. ↝ MAY BE REFETCHED WHILE MAINTAINING CLIENT-SIDE STATE INSIDE OF THE TREE. RSC: BENEFITS
  149. REACT SERVER COMPONENTS 🟡 WHILE OUR JS BUNDLES GET SMALLER,

    THE HTML FILE GETS LARGER 🟡 MUCH MORE ORCHESTRATION NEEDED 🟡 STILL EXPERIMENTAL (IMHO 🌶) 🟡 THERE ISN'T MUCH TOOLING YET 🟡 ONLY FEW OPTIONS FOR DEVELOPERS TO LEVERAGE RSC NOT GREAT 🟢 THE CODE FOR SERVER COMPONENTS IS NEVER DELIVERED TO THE CLIENT 🟢 ACCESS TO THE BACK-END FROM THE TREE 🟢 MAY BE REFETCHED WHILE MAINTAINING CLIENT-SIDE STATE INSIDE OF THE TREE GREAT
  150. CODE EXTRACTION: PRIOR ART < ! - - Database, file,

    and socket access from JavaScript - - > <script runat="server"> var resultSet = Jaxer.DB.execute("SELECT * FROM myTable"); var newPrice = resultSet.rows[0].price; </script> < ! - - Directly call server-side functions from the browser - - > <script runat="server-proxy"> function getPriceFromServer() { return 42; } </script> <button onclick="alert(getPriceFromServer())">Price</button> < ! - - Share validation code on the browser and server - - > <script runat="both"> function validateCreditCard(number) {} </script>
  151. CODE EXTRACTION: PRIOR ART < ! - - Database, file,

    and socket access from JavaScript - - > <script runat="server"> var resultSet = Jaxer.DB.execute("SELECT * FROM myTable"); var newPrice = resultSet.rows[0].price; </script> < ! - - Directly call server-side functions from the browser - - > <script runat="server-proxy"> function getPriceFromServer() { return 42; } </script> <button onclick="alert(getPriceFromServer())">Price</button> < ! - - Share validation code on the browser and server - - > <script runat="both"> function validateCreditCard(number) {} </script>
  152. ↝ A NEXT.JS FEATURE. ↝ AIMS TO IMPROVE THE LOADING

    SPEED FOR PAGES WITH MOSTLY STATIC CONTENT + A FEW DYNAMIC PARTS. ↝ STATIC SHELL SERVED QUICKLY FROM THE EDGE. ↝ PLACEHOLDERS LEFT FOR DYNAMIC CONTENT. PARTIAL PRERENDERING
  153. PARTIAL PRERENDERING PAGE LAYOUT NAVBAR PRODUCT INFORMATION RECOMMENDED PRODUCTS CART

    RENDERS ALL THE STATIC CONTENT INSTANTLY FROM THE EDGE
  154. PARTIAL PRERENDERING PAGE LAYOUT NAVBAR PRODUCT INFORMATION RECOMMENDED PRODUCTS CART

    WHILE THE PAGE LOADS (STYLES, SCRIPTS, ETC) RENDER THE REST FOR EACH USER, DYNAMICALLY
  155. PARTIAL PRERENDERING BUILD TIME STATIC SHELL CDN USER REQ EDGE

    SERVER BROWSER DYNAMIC CONTENT STATIC CONTENT VISIBLE FULLY RENDERED PAGE GENERATE DYNAMIC CONTENT GENERATE STATIC CONTENT DEPLOY ROUTE TO THE NEAREST SERVE STATIC SHELL STREAM
  156. PARTIAL PRERENDERING BUILD TIME STATIC SHELL CDN USER REQ EDGE

    SERVER BROWSER DYNAMIC CONTENT STATIC CONTENT VISIBLE FULLY RENDERED PAGE GENERATE DYNAMIC CONTENT GENERATE STATIC CONTENT DEPLOY ROUTE TO THE NEAREST SERVE STATIC SHELL STREAM
  157. ↝ MANY PERFORMANCE OPTIMIZATIONS CAN BE MADE WHEN WE CAN

    PREDICT WHAT USERS MIGHT DO. ↝ THERE ARE A FEW SIMPLE BUT EFFECTIVE WAYS FOR DEVELOPERS TO HELP THE BROWSER STAY ONE STEP AHEAD OF THE USER AND KEEP PAGES FAST. PREDICT WORK
  158. ↝ PREDICT TAB NAVIGATION IN DASHBOARDS. ↝ PREFETCH THE NEXT

    ROUTE AFTER LOGIN SUCCESS. ↝ PRECONNECT ANALYTICS ENDPOINTS AFTER CONSENT. ↝ PRERENDER CHECKOUT AFTER CART INTERACTION. ↝ PREFETCH THE NEXT ARTICLE WHEN THE READER SCROLLS 75%. PREDICT WORK: IDEAS
  159. ↝ IT ALLOWS THE BROWSER TO SET UP EARLY CONNECTIONS

    BEFORE THE REQUEST IS ACTUALLY SENT TO THE SERVER. THIS INCLUDES: ↝ TLS NEGOTIATIONS ↝ TCP HANDSHAKES ↝ ELIMINATES ROUND-TRIP LATENCY. PRECONNECT: OVERVIEW
  160. PRECONNECT: OVERVIEW 100MS 200MS 300MS 400MS 500MS 600MS 700MS HTML

    CSS FONT 1 FONT 2 FONTS START LOADING FONTS RENDERED
  161. PRECONNECT: OVERVIEW 100MS 200MS 300MS 400MS 500MS 600MS 700MS HTML

    CSS FONT 1 FONT 2 FONTS START LOADING FONTS RENDERED FONT 1 FONT 2
  162. PRECONNECT: ↝ GOOGLE FONTS BEFORE CSS LOADS. ↝ THE API

    ORIGIN AFTER LOGIN SUCCESS. ↝ THE CDN HOSTING HERO IMAGE. ↝ THE ANALYTICS ENDPOINT AFTER CONSENT. ↝ THE CHECKOUT DOMAIN FROM THE PRODUCT PAGE. PRECONNECT: IDEAS
  163. ↝ DESIGNED TO IMPROVE PERFORMANCE FOR FUTURE DOCUMENT NAVIGATIONS. ↝

    A MODERN AND MORE EXPRESSIVE REPLACEMENT FOR OLDER PRERENDER TECHNIQUES. ↝ PREFETCH/PRERENDER DOCUMENTS AHEAD OF CLICKS. ↝ WORKS BEST FOR MPAS OR ROUTE-LEVEL TRANSITIONS. SPECULATION RULES: OVERVIEW
  164. SPECULATION RULES: OVERVIEW <script type="speculationrules"> { "prefetch": [{ "source": "list",

    "urls": ["/checkout"] }] } </script> <script type="speculationrules"> { "prerender": [{ "where": { "href_matches": "/product/ * " } }] } </script>
  165. ↝ PREFETCH /DASHBOARD AFTER LOGIN SUCCESS. ↝ PREFETCH /CHECKOUT AFTER

    CART INTERACTION. ↝ PREFETCH TOP RESULT LINKS IN THE VIEWPORT. ↝ PRERENDER LIKELY NEXT SETTINGS TAB. SPECULATION RULES: IDEAS
  166. ↝ TELL THE BROWSER WHAT MATTERS FIRST. ↝ OVERRIDE DEFAULT

    FETCH HEURISTICS WHEN NEEDED. ↝ OPTIMIZE LCP RESOURCES EXPLICITLY. PRIORITY HINTS: OVERVIEW
  167. PRIORITY HINTS: OVERVIEW < ! - - Increase the priority

    of the LCP image - - > <img src="image.jpg" fetchpriority="high" /> < ! - - Lower the priority of above-the-fold images - - > <ul class="carousel"> <img src="img/carousel-1.jpg" fetchpriority="high" /> <img src="img/carousel-2.jpg" fetchpriority="low" /> <img src="img/carousel-3.jpg" fetchpriority="low" /> </ul> < ! - - Reprioritize scripts - - > <script src="async_but_important.js" async fetchpriority="high"></script> <script src="blocking_but_unimportant.js" fetchpriority="low"></script>
  168. PRIORITY HINTS: OVERVIEW < ! - - Increase the priority

    of the LCP image - - > <img src="image.jpg" fetchpriority="high" /> < ! - - Lower the priority of above-the-fold images - - > <ul class="carousel"> <img src="img/carousel-1.jpg" fetchpriority="high" /> <img src="img/carousel-2.jpg" fetchpriority="low" /> <img src="img/carousel-3.jpg" fetchpriority="low" /> </ul> < ! - - Reprioritize scripts - - > <script src="async_but_important.js" async fetchpriority="high"></script> <script src="blocking_but_unimportant.js" fetchpriority="low"></script>
  169. PRIORITY HINTS: OVERVIEW / / Important validation data const user

    = await fetch("/user"); / / Less important content data const relatedPosts = await fetch("/posts/suggested", { priority: "low" });
  170. PRIORITY HINTS: OVERVIEW / / Important validation data const user

    = await fetch("/user"); / / Less important content data const relatedPosts = await fetch("/posts/suggested", { priority: "low" });
  171. ↝ BOOST HERO IMAGE PRIORITY. ↝ PRIORITIZE ROUTE TRANSITION BUNDLES.

    ↝ DEPRIORITIZE RECOMMENDATION PANELS. ↝ DEPRIORITIZE BELOW-FOLD IMAGES. ↝ CONTROL HYDRATION FETCH ORDERING. PRIORITY HINTS: IDEAS
  172. ↝ ZERO JAVASCRIPT. ↝ DEFER IMAGE AND IFRAME DOWNLOADS AUTOMATICALLY.

    ↝ LET THE BROWSER DECIDE OPTIMAL FETCH TIMING. ↝ REMOVE OFF-SCREEN CONTENT FROM THE CRITICAL RENDERING PATH. NATIVE LAZY LOADING: OVERVIEW
  173. NATIVE LAZY LOADING: OVERVIEW <img src="/gallery-1.jpg" loading="lazy" width="800" height="600" />

    <iframe src="https://maps.example.com" loading="lazy" width="600" height="400"> </iframe>
  174. ↝ PRODUCT GALLERY IMAGES. ↝ EMBEDDED YOUTUBE PLAYERS. ↝ MAPS

    AND CHAT WIDGETS. ↝ ANALYTICS DASHBOARDS BELOW THE FOLD. ↝ ROUTE-LEVEL IFRAMES IN MICRO-FRONTENDS. NATIVE LAZY LOADING: IDEAS
  175. “Lazy-loading iframes can lead to 2-3% median data savings, 1-2%

    FCP reductions, and 2% FID improvements at the 95th percentile.” Chrome team’s research • 2019
  176. ALIASING REACT TO PREACT 📅 2018 📅 2024 REACT: INTERNALS

    AND ADVANCED PERFORMANCE PATTERNS 2024 2018
  177. PREACT: OVERVIEW ↝ WAY SMALLER BUNDLE (APPROXIMATELY 3.5KB). ↝ FASTER

    VIRTUAL DOM IMPLEMENTATION. ↝ MORE EFFECTIVE MEMORY USAGE.
  178. PREACT: CASE STUDY 205.9KB MIN + GZIP / NO POLYFILLS

    175.26KB MIN + GZIP / NO POLYFILLS
  179. DATA-ORIENTED DESIGN ↝ A COLLECTION OF TECHNIQUES TO ANALYZE THE

    ACCESS PATTERNS OF THE DIFFERENT KINDS OF DATA AND SELECT DATA STRUCTURES THAT OPTIMALLY LEVERAGE THE UNDERLYING HARDWARE. ↝ THE OPTIMIZATIONS ARE OFTEN RELATED TO OPTIMIZING USAGE OF THE CPU CACHE, LIMITING LOADING/STORING TO RAM (CACHE MISSES), AND USAGE OF SIMD INSTRUCTIONS.
  180. BECAUSE… CPUs ARE FAST ↝ BASIC MATH CAN BE DONE

    IN A FEW CYCLES. ↝ COMPLEX MATH REQUIRES A FEW MORE CYCLES—BUT IT’S STILL OK. ↝ SIMD MAKES THE THROUGHPUT EVEN BETTER BY PROCESSING MULTIPLE VALUES IN THE TIME IT TAKES TO DO A SINGLE INSTRUCTION.
  181. BUT… MEMORY IS NOT AS FAST ↝ CPUS CAN ONLY

    OPERATE ON DATA THAT IS PHYSICALLY CO-LOCATED. ↝ EITHER IN A REGISTER OR IN THE L1 CACHE. ↝ EVERYTHING ELSE NEEDS TO BE LOADED FIRST.
  182. CPU MEMORY 100 NS ⁵ L1 CACHE 0.5 NS ⁵

    L2 CACHE 4 NS ⁵ BUT… MEMORY IS NOT AS FAST
  183. BUT… MEMORY IS NOT AS FAST ↝ MEMORY ACCESS IS

    SLOW. ↝ CACHING CAN ALLEVIATE MOST OF THE LATENCY IF THE CPU CAN PREDICT THE ACCESS PATTERN—USUALLY, THE SIMPLE ONES. ↝ LINEAR PATTERNS ARE USUALLY GOOD. ↝ RANDOM PATTERNS ARE USUALLY BAD.
  184. ARRAY OF STRUCTURES STRUCTURE OF ARRAYS AOS ⨯ SOA type

    Entity = { position: { x: number; y: number }; velocity: { x: number; y: number }; hitPoints: number; }; const entities: Entity[] = [ { position: { x: 0, y: 0 }, velocity: { x: 1, y: 1 }, hitPoints: 100 }, { position: { x: 10, y: 5 }, velocity: { x: -1, y: 0 }, hitPoints: 80 }, / / . . . ]; const positions = new Float32Array([0, 0, 10, 5 / * const velocities = new Float32Array([1, 1, -1, 0 / * const hitPoints = new Int16Array([100, 80 / * / const i = 0; console.log(positions[i * 2], positions[i * 2 + 1]); / console.log(velocities[i * 2], velocities[i * 2 + 1]); console.log(hitPoints[i]);
  185. ARRAY OF STRUCTURES STRUCTURE OF ARRAYS AOS ⨯ SOA type

    Entity = { position: { x: number; y: number }; velocity: { x: number; y: number }; hitPoints: number; }; const entities: Entity[] = [ { position: { x: 0, y: 0 }, velocity: { x: 1, y: 1 }, hitPoints: 100 }, { position: { x: 10, y: 5 }, velocity: { x: -1, y: 0 }, hitPoints: 80 }, . ]; const positions = new Float32Array([0, 0, 10, 5 / * . . . * /]); const velocities = new Float32Array([1, 1, -1, 0 / * . . . * /]); const hitPoints = new Int16Array([100, 80 / * . . . * /]); / / Entity i = index in all arrays const i = 0; console.log(positions[i * 2], positions[i * 2 + 1]); / / x, y console.log(velocities[i * 2], velocities[i * 2 + 1]); console.log(hitPoints[i]);
  186. ARRAY OF STRUCTURES STRUCTURE OF ARRAYS AOS ⨯ SOA ✅

    EASY TO READ, WRITE, AND MODEL FOR US. ✅ ENTITIES ARE INTUITIVE BUNDLES. ❌ POOR DATA LOCALITY. ❌ ITERATING OVER MILLIONS SCALES BADLY. ❌ HARD TO PARALLELIZE BECAUSE DATA IS INTERLEAVED. ✅ EXCELLENT DATA LOCALITY. ✅ CACHE-FRIENDLY + SIMD ACCELERATION POSSIBLE. ✅ PARALLELIZABLE: SYSTEMS OPERATE ON “COLUMNS” INDEPENDENTLY. ❌ LESS INTUITIVE FOR DEVS USED TO OBJECTS. ❌ HARDER TO DEBUG AN ENTITY.
  187. ARRAY OF STRUCTURES STRUCTURE OF ARRAYS AOS ⨯ SOA ✅

    EASY TO READ, WRITE, AND MODEL FOR US. ✅ ENTITIES ARE INTUITIVE BUNDLES. ❌ POOR DATA LOCALITY. ❌ ITERATING OVER MILLIONS SCALES BADLY. ❌ HARD TO PARALLELIZE BECAUSE DATA IS INTERLEAVED. ✅ EXCELLENT DATA LOCALITY. ✅ CACHE-FRIENDLY + SIMD ACCELERATION POSSIBLE. ✅ PARALLELIZABLE: SYSTEMS OPERATE ON “COLUMNS” INDEPENDENTLY. ❌ LESS INTUITIVE FOR DEVS USED TO OBJECTS. ❌ HARDER TO DEBUG AN ENTITY.
  188. ARRAY OF STRUCTURES DX DY UNITS 0 ⇢ 2 UNITS

    3 ⇢ 5 UNITS … ⇢ N X Y X Y X Y X Y X Y X Y X Y X Y X Y DX DY DX DY DX DY DX DY DX DY DX DY DX DY DX DY HP HP HP HP HP HP HP HP HP
  189. ARRAY OF STRUCTURES HP HP HP HP HP HP HP

    HP HP UNITS 0 ⇢ 2 UNITS 3 ⇢ 5 UNITS … ⇢ N
  190. STRUCTURE OF ARRAYS HP POSITIONS VELOCITIES HIT POINTS X Y

    X Y X Y X Y X Y X Y X Y DX DY DX DY DX DY DX DY DX DY DX DY DX DY HP HP HP HP HP HP HP HP HP HP HP HP HP
  191. STRUCTURE OF ARRAYS POSITIONS VELOCITIES HIT POINTS X Y X

    Y X Y X Y X Y X Y DX DY DX DY DX DY DX DY DX DY DX DY HP HP HP HP HP HP HP HP HP HP HP HP THREAD A THREAD B THREAD C
  192. DATA-ORIENTED DESIGN ↝ SMALL LOOPS THAT OPERATE ON ARRAYS OF

    FIELDS. ↝ MINIMIZE THE AMOUNT OF DATA IN CACHE THAT ISN’T READ OR WRITTEN DURING THE UPDATE. ↝ SEVERAL TRANSFORMS CAN RUN IN PARALLEL ON THE SAME LOGICAL OBJECT IF THEY DON’T SHARE FIELDS.
  193. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS #experiment 🧪 Comparing two

    di ff erent memory layouts for the same data with @pmndrs/koota.
  194. “So here’s my advice for anyone who wants to make

    a dent in the future of web development: time to learn how compilers work.” Compilers are the New Frameworks • Tom Dale, 2017
  195. “Reactive systems have existed even in this space for years.

    In fact, reactivity was seen as a bad thing for a while with the rise of the popularity of React. The thing that has made reactive programming interesting again are compilers.” Marko: Compiling Fine-Grained Reactivity • Ryan Carniato, 2022
  196. “Static analysis and compilation let us take what we know

    of your code's structure and optimize the creation paths as we already know what you are trying to create.” Marko: Compiling Fine-Grained Reactivity • Ryan Carniato, 2022
  197. ↝ LINTERS: ESLINT (2013), TSLINT (2015), BIOME (2023), OXLINT (2023)…

    ↝ FORMATTERS: PRETTIER (2017), DPRINT (2020), BIOME (2023)… ↝ BUNDLERS: WEBPACK (2012), ROLLUP (2015), VITE (2020), ESBUILD (2020), RSPACK (2022), ROLLDOWN (2023)… COMPILERS & STATIC ANALYSIS
  198. ↝ TRANSPILERS: BABEL (2014), SWC (2020)… ↝ TYPE CHECKERS: TYPESCRIPT

    (2012), FLOW (2014)… ↝ MINIFIERS: UGLIFYJS (2010), TERSER (2018)… ↝ CSS PROCESSING: POSTCSS (2013), CSSO (2015), CSSNANO (2015), LIGHTNINGCSS (2022)… COMPILERS & STATIC ANALYSIS
  199. ↝ IMPROVE THE RENDERING PERFORMANCE BY AUTOMATICALLY GENERATING THE EQUIVALENT

    OF useMemo, useCallback, AND memo CALLS. ↝ MINIMIZE THE COST OF RE-RENDERING WHILE RETAINING REACT’S PROGRAMMING MODEL. ↝ AUTOMATIC OPTIMIZATION COMPILER. REACT COMPILER: OVERVIEW
  200. ↝ IT'S A CLASS OF TECHNIQUES THAT ATTEMPT TO DETERMINE

    IF VARIABLES REFER TO THE SAME UNDERLYING DATA. ↝ IT HELPS COMPILERS GENERATE EFFICIENT AND OPTIMIZED CODE. ALIAS ANALYSIS: OVERVIEW
  201. ALIAS ANALYSIS: OVERVIEW function example(arr) { arr[0] = 10; const

    value = arr[0]; return value; } DOES `VALUE` ALWAYS EQUAL 10?
  202. ALIAS ANALYSIS: EX. #1 function Component({ a, b }) {

    const x = []; x.push(a); return <Foo x={x} />; } function Component({ a, b }) { > } — ALIAS ANALYSIS IN THE REACT COMPILER • SATHYA GUNASEKARAN, 2024
  203. ALIAS ANALYSIS: EX. #1 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { } function Component({ a, b }) { const x = useMemo(() = > { const x = []; x.push(a); return x; }, [a]); return <Foo x={x} />; }
  204. ALIAS ANALYSIS: EX. #1 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { } function Component({ a, b }) { > } ✅
  205. ALIAS ANALYSIS: EX. #2 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { const x = []; x.push(a); const y = x; y.push(b); return <Foo x={x} />; } function Component({ a, b }) { > > }
  206. ALIAS ANALYSIS: EX. #2 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { } function Component({ a, b }) { const x = useMemo(() = > { const x = []; x.push(a); return x; }, [a]); const y = useMemo(() = > { const y = x; y.push(b); return y; }, [x, b]); return <Foo x={x} />; }
  207. ALIAS ANALYSIS: EX. #2 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { const x = []; x.push(a); const y = x; y.push(b); return <Foo x={x} />; } function Component({ a, b }) { > > } ❌
  208. ALIAS ANALYSIS: EX. #2 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { } function Component({ a, b }) { const x = useMemo(() = > { const x = []; x.push(a); const y = x; y.push(b); return y; }, [a, b]); return <Foo x={x} />; }
  209. ALIAS ANALYSIS: EX. #2 — ALIAS ANALYSIS IN THE REACT

    COMPILER • SATHYA GUNASEKARAN, 2024 function Component({ a, b }) { } function Component({ a, b }) { const x = useMemo(() => { const x = []; x.push(a); const y = x; y.push(b); return y; }, [a, b]); return <Foo x={x} />; } ✅
  210. ↝ A TECHNIQUE WHERE EVERY VARIABLE HAS A SINGLE DEFINITION.

    MAINTAINING USE-DEFINED CHAINS IS EASIER, SINCE FOR EVERY USE, YOU HAVE TO KEEP TRACK OF ONLY ONE DEFINITION. ↝ THE SIMPLIFIED STRUCTURE ENABLES MORE POWERFUL AND EFFICIENT OPTIMIZATION TECHNIQUES. SSA FORM: OVERVIEW
  211. BEFORE AFTER SSA FORM: OVERVIEW x = y - z

    s = x + s x = s + p s = z * q s = x * s x = y - z s2 = x + s x2 = s2 + p s3 = z * q s4 = x2 * s3
  212. BEFORE AFTER SSA FORM: OVERVIEW x = y - z

    s = x + s x = s + p s = z * q s = x * s x = y - z s2 = x + s x2 = s2 + p s3 = z * q s4 = x2 * s3
  213. SSA FORM: EXAMPLE function Component({ colors }) { let styles

    = { colors }; return <Item styles={styles} />; } function Component(props) { const $ = useMemoCache(2); const { colors } = props; let t0; if ($[0] ! = = colors) { t0 = { colors }; $[0] = colors; $[1] = t0; } else { t0 = $[1]; } const styles = t0; return <Item styles={styles} />; } — COMPILER THEORY AND REACTIVITY • SATHYA GUNASEKARAN, 2024
  214. BROKEN RULES OF REACT export default function usePrevious<T>(state: T): T

    | undefined { const ref = useRef<T>(); useEffect(() = > { ref.current = state; }); return ref.current; }
  215. ↝ TAILWIND DOESN'T PARSE OR EXECUTE ANY OF THE CODE.

    IT USES REGULAR EXPRESSIONS TO EXTRACT EVERY STRING THAT COULD POSSIBLY BE A CLASS NAME. ↝ IT WILL ONLY FIND CLASSES THAT EXIST AS COMPLETE UNBROKEN STRINGS. ↝ YOU CAN'T CONSTRUCT CLASS NAMES DYNAMICALLY. TEMPLATE WITH INTERPOLATIONS
  216. COMPUTED KEYS const [currentLevel, setCurrentLevel] = useState(difficulty) const useRatingSystem =

    (props: RecipeProps) = > { return { [props.difficulty]: "⭐".repeat(props.difficulty === 'easy' ? 1 : props.difficulty === 'medium' ? 2 : 3) } } const rating = useRatingSystem({ difficulty: currentLevel })
  217. COMPUTED KEYS const [currentLevel, setCurrentLevel] = useState(difficulty) const useRatingSystem =

    (props: RecipeProps) = > { return { [props.difficulty]: "⭐".repeat(props.difficulty === 'easy' ? 1 : props.difficulty === 'medium' ? 2 : 3) } } const rating = useRatingSystem({ difficulty: currentLevel })
  218. ↝ TRACKS VARIABLES AND DETERMINES THEIR SCOPES. ↝ IDENTIFIES DEPENDENCIES

    AND DETECTS REACTIVE STATEMENTS AND EVENT HANDLERS. ↝ SCOPES STYLES TO COMPONENTS AND OPTIMIZES CSS FOR PERFORMANCE. …AND MUCH MORE! SVELTE
  219. ↝ EVERY VARIABLE THAT HAS BEEN REASSIGNED OR MUTATED AND

    REFERENCED IN THE TEMPLATE WILL HAVE THE $$invalidate FUNCTION INSERTED RIGHT AFTER THE ASSIGNMENT OR MUTATION. ↝ IT MARKS THE VARIABLE DIRTY AND SCHEDULES AN UPDATE FOR THE COMPONENT. SVELTE: $$invalidate
  220. SOLID.JS: STATIC JSX EXPRESSIONS <MyComponent static={ / * @once *

    / state.wontUpdate} /> <MyComponent>{ / * @once * / state.wontUpdate}</MyComponent> <div style={{ width: / * @once * / props.width, height: / * @once * / props.height, color: props.color, }} />
  221. #definition 🧐 jscodeshift is a tool that runs a transformation

    script over one or more JavaScript or TypeScript fi les.
  222. JSCODESHIFT: HELLO WORLD export default function transformer(file: FileInfo, api: API)

    { const j = api.jscodeshift; const root = j(file.source); const variableDeclarators = root.findVariableDeclarators('foo'); variableDeclarators.renameTo('bar'); return root.toSource(); }
  223. JSCODESHIFT: HELLO WORLD export default function transformer(file: FileInfo, api: API)

    { const j = api.jscodeshift; const root = j(file.source); const variableDeclarators = root.findVariableDeclarators('foo'); variableDeclarators.renameTo('bar'); return root.toSource(); }
  224. JSCODESHIFT: HELLO WORLD export default function transformer(file: FileInfo, api: API)

    { const j = api.jscodeshift; const root = j(file.source); const variableDeclarators = root.findVariableDeclarators('foo'); variableDeclarators.renameTo('bar'); return root.toSource(); }
  225. #experiment 🧪 Writing our fi rst codemod using jscodeshift. REACT:

    INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  226. GRADUAL ROLLOUT OF TWO ENTIRELY DIFFERENT, FEATURE -FLAG-PROTECTED, BUILDS OF

    THE SAME CODEBASE, WITH: ↝ DIFFERENT VERSIONS OF DEV DEPENDENCIES. ↝ DIFFERENT VERSIONS OF APP DEPENDENCIES. ↝ DIFFERENT STRATEGIES FOR BUNDLING AND SERVING. STATIC ANALYSIS ENABLED…
  227. ↝ METRICS AROUND USER-GENERATED CONTENT BASED ON PLUGIN COMPOSITION. ↝

    ACTUAL DATA IS THE SINGLE SOURCE OF TRUTH AND CONSISTENCY IS GUARANTEED ACROSS ALL API ENDPOINTS AND THE REACT APP. ↝ RAPID ITERATION WITH INSTANT TYPED APIS AND ENHANCED DX WHEN IMPLEMENTING NEW METRICS. STATIC ANALYSIS ENABLED…
  228. #experiment 🧪 Writing our fi rst codemod using ast-grep. REACT:

    INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  229. TS-MORPH: HELLO WORLD AFTER BEFORE interface ApiResponse { userData?: UserData;

    apiVersion?: string; isActive?: boolean; userPreferences?: UserPreferences; } interface Welcome { the_user_data?: UserData; "api-version"?: string; isActive?: boolean; user_preferences?: any; }
  230. TS-MORPH: HELLO WORLD sourceFile.getInterfaces().forEach(iface = > { / / Convert

    snake_case to camelCase const newName = toCamelCase(iface.getName()); iface.rename(newName); / / Transform properties iface.getProperties().forEach(prop = > { const propName = prop.getName(); if (propName.includes('_') | | propName.includes('-')) { const camelName = toCamelCase(propName.replace(/["-]/g, '_')); prop.rename(camelName); } / / Replace 'any' types with proper interfaces if (prop.getTypeNode()?.getText() === 'any') { prop.setType('UserPreferences'); } }); });
  231. sourceFile.getInterfaces().forEach(iface = > { / / Convert snake_case to camelCase

    const newName = toCamelCase(iface.getName()); iface.rename(newName); / / Transform properties iface.getProperties().forEach(prop = > { const propName = prop.getName(); if (propName.includes('_') | | propName.includes('-')) { const camelName = toCamelCase(propName.replace(/["-]/g, '_')); prop.rename(camelName); } / / Replace 'any' types with proper interfaces if (prop.getTypeNode()?.getText() === 'any') { prop.setType('UserPreferences'); } TS-MORPH: HELLO WORLD
  232. #experiment 🧪 Writing our fi rst codemod using ts-morph. REACT:

    INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  233. MILLION LINT: COMPILER function App({ start }) { const [count,

    setCount] = useState(start); useEffect(() = > { console.log("double: ", count * 2); }, [count]); return <Button onClick={() = > setCount(count + 1)}>{count}</Button>; } — MILLION LINT IS IN PUBLIC BETA • 2024
  234. MILLION LINT: COMPILER function App({ start }) { Million.capture({ start

    }); const [count, setCount] = Million.capture(useState)(start); useEffect( () = > { console.log("double: ", count * 2); }, Million.capture([count]), ); return Million.capture( <Button onClick={() = > setCount(count + 1)}>{count}</Button>, ); } — MILLION LINT IS IN PUBLIC BETA • 2024
  235. MILLION LINT: COMPILER [ 'src/App.jsx': { components: { App: {

    renders: [{ count: 7, time: 0.1 }, . . . ], instances: 3, count: 70, time: 1, location: [13, 0, 23, 1], } } } ]; [ { kind: 'state', count: 7, time: 0.1, changes: [{ prev: 0, next: 8 }, . . . ], } ]; — MILLION LINT IS IN PUBLIC BETA • 2024
  236. TWO EXAMPLES: ↝ MAGLEV: GETS TYPE FEEDBACK FROM THE INTERPRETER

    AND RUNS QUICK OPTIMIZATIONS. ↝ TURBOFAN: TRANSLATES BYTE-CODE INTO HIGHLY OPTIMIZED MACHINE CODE, USING SEA OF NODES (SON) AND CONTROL-FLOW GRAPH (CFG) IR. COMPILERS & V8
  237. TWO EXAMPLES: ↝ DFG JIT: BUILDS A DATA-FLOW GRAPH IR,

    USES PROFILING TO SPECIALIZE TYPES, REMOVE CHECKS, AND MORE, BUT WITH MODERATE COMPILE COST. ↝ FTL JIT: USES MULTIPLE IR (INCLUDING B3 AND LLVM) FOR AGGRESSIVE OPTIMIZATIONS AND HIGHER THROUGHPUT FOR HOT CODE. COMPILERS & JAVASCRIPTCORE
  238. ↝ ⭐ BEHAVIOR ANALYSIS: RAGE CLICKS • THRASHED CURSOR RANDOM

    SCROLLING • BACKTRACKING ↝ ⭐ RANDOM STUFF: VISIBILITY STATE • LAYOUT INSTABILITY • CUSTOM METRICS ↝ PROFILING: LONG TASKS • LONG ANIMATION FRAMES • SELF PROFILING • MEMORY USAGE ↝ SENSORS: NETWORK STATUS • BATTERY STATUS • ETC. THIS SECTION PRESENTS…
  239. “Rage clicks occur when users rapidly click (or tap) on

    your site or app. Rage clicking is the digital equivalent of cursing to release frustration.” Severity and impact of computer user frustration • 2006
  240. DEAD CLICKS ↝ WHEN USERS CLICK AN ELEMENT, BUT THE

    CLICK HAS NO EFFECT ON THE PAGE. ↝ UNLIKE RAGE CLICKS, THEY DON'T REQUIRE RAPID- FIRE, BACK-TO-BACK CLICKS TO TRIGGER. ↝ LIKE RAGE CLICKS, THERE IS A CHANCE THAT A DEAD CLICK IS NOT OUT OF FRUSTRATION—A FALSE POSITIVE.
  241. DEAD CLICKS E.G.: ↝ CLICKING PARAGRAPHS OF TEXT TO FOCUS

    ATTENTION AS YOU STRUGGLE TO INTERNALIZE A CHALLENGING CONCEPT. ↝ CLICKING THE BACKGROUND OF A PAGE TO ESCAPE AN OVERLAY.
  242. THRASHED CURSOR ↝ MOVEMENT COVERING A HIGH DISTANCE TRAVELLED IN

    A SHORT AMOUNT OF TIME, WITH NO INTENTIONALITY. ↝ INDICATES IMPATIENCE, DOUBT, DIFFICULTY, OR ANXIETY. ↝ IT OFTEN HAPPENS WHEN THE USER IS WAITING BUT IT CAN ALSO BE ASSOCIATED WITH HIGH COGNITIVE LOAD.
  243. THRASHED CURSOR E.G.: ↝ PERFORMANCE: IF IT OCCURS WHILE USERS

    ARE WAITING FOR A VIDEO TO BUFFER, A PICTURE WINDOW TO OPEN, OR THE NEXT ROUTE TO LOAD. ↝ COGNITIVE LOAD: IF IT OCCURS WHILE THEY'RE ENGAGED IN AN ACT OF FILLING OUT, CREATING, WRITING, OR OTHER CHALLENGING TASK.
  244. RANDOM SCROLLING ↝ RAPID SCROLLING, OFTEN THROUGH LARGE CHUNKS. ↝

    INDICATES THAT A USER IS ON THE HUNT FOR THEIR NEXT STEP. ↝ PEOPLE HAVE LIMITED ATTENTION SPANS AND SCROLLING FEELS LIKE EXTRA WORK SO THIS CAN QUICKLY CAUSE USERS TO LOSE HOPE.
  245. RANDOM SCROLLING IT CAN INDICATE… ↝ THAT CONTENT IS TOO

    LONG AND CAUSES USERS TO BECOME IMPATIENT. ↝ WHICH INFORMATION YOUR USERS CONSIDER USEFUL. ↝ THE RELATIONSHIP BETWEEN CONTENT AND YOUR CALLS- TO-ACTION.
  246. LONG TASKS: OVERVIEW new PerformanceObserver((list) = > { for (const

    entry of list.getEntries()) { console.log("Blocked for:", entry.duration); entry.attribution?.forEach((source) = > { console.log("Source:", source.containerSrc); }); } }).observe({ type: "longtask", buffered: true });
  247. DETECT: ↝ HYDRATION BLOCKING THE MAIN THREAD. ↝ LARGE BUNDLE

    EXECUTION PAUSES. ↝ THIRD-PARTY IFRAME BLOCKING INPUT. ↝ EXPENSIVE LAYOUT RECALCULATIONS. LONG TASKS: IDEAS
  248. DETECT: ↝ INP REGRESSIONS. ↝ RENDERING PIPELINE BOTTLENECKS. ↝ ANIMATION

    FRAME DROPS. ↝ SLOW CSS/LAYOUT RECALCULATIONS. ↝ SLOW COMPOSITING PHASES. LONG ANIMATION FRAMES: IDEAS
  249. SELF PROFILING: OVERVIEW const profiler = new Profiler({ sampleInterval: 10,

    maxBufferSize: 10000 }); await doWork(); const profile = await profiler.stop(); console.log(profile.samples);
  250. ↝ PROFILE REAL-WORLD HYDRATION BOTTLENECKS. ↝ PROFILE THIRD-PARTY SCRIPT EXECUTION

    TIME. ↝ DETECT HOT LOOPS IN DATA PROCESSING PIPELINES. ↝ DETECT REGRESSIONS AFTER FEATURE ROLLOUT. SELF PROFILING: IDEAS
  251. MEMORY USAGE: OVERVIEW const result = await performance.measureUserAgentSpecificMemory(); console.log("Total memory:",

    result.bytes); result.breakdown.forEach((entry) = > { console.log(entry.types, entry.bytes); });
  252. MEMORY USAGE: LEAKS #1 const obj = { a: new

    Array(1000), b: new Array(2000) }; setInterval(() = > { console.log(obj.a); }, 1000);
  253. MEMORY USAGE: LEAKS #4 const cache = new Map(); function

    track(el) { cache.set(el, new Array(100000).fill("data")); }
  254. ↝ FORGETTING TO UNREGISTER AN EVENT LISTENER. ↝ ACCIDENTALLY CAPTURING

    OBJECTS FROM AN IFRAME. ↝ NOT CLOSING A WORKER. ↝ ACCUMULATING OBJECTS IN ARRAYS. ↝ AND MUCH MORE! MEMORY USAGE: LEAKS
  255. ↝ DETECT MEMORY LEAKS AFTER ROUTE TRANSITIONS. ↝ DETECT IFRAME

    MEMORY ISOLATION ISSUES. ↝ DETECT DOM NODE ACCUMULATION REGRESSIONS. ↝ MEASURE SPA CACHE GROWTH OVER TIME. ↝ COMPARE THE MEMORY COST OF FEATURE VARIANTS. MEMORY USAGE: IDEAS
  256. ↝ MAIN-THREAD BLOCKING ↝ WHERE TIME GOES. ↝ FRAME PIPELINE

    BLOCKING ↝ WHERE FRAMES DROP. ↝ CPU HOTSPOT ATTRIBUTION ↝ WHAT CODE RUNS. ↝ MEMORY HOTSPOT ATTRIBUTION ↝ WHERE MEMORY GROWS. PROFILING
  257. ↝ DISABLE ROUTE PREFETCHING ON SLOW CONNECTIONS. ↝ SKIP ANALYTICS

    UPLOADS WHEN RTT IS HIGH. ↝ LOAD LOWER-RESOLUTION ON CONSTRAINED BANDWIDTH. ↝ ADAPT TO SITUATIONS WHEN USERS ARE OFFLINE. ↝ RESPECT DATA SAVING AS A USER PERFORMANCE PREFERENCE SIGNAL. NETWORK STATUS: IDEAS
  258. NETWORK STATUS: IDEAS switch (connectionType) { case "4g": return <Video

    src={videoSrc} />; case "3g": return <Image src={imageSrc.hiRes} alt={alt} />; default: return <Image src={imageSrc.lowRes} alt={alt} />; }
  259. BATTERY STATUS: OVERVIEW const batteryInfo = await navigator.getBattery(); batteryInfo.addEventListener("chargingchange", listener);

    batteryInfo.addEventListener("chargingtimechange", listener); batteryInfo.addEventListener("dischargingtimechange", listener); batteryInfo.addEventListener("levelchange", listener);
  260. ↝ DISABLE BACKGROUND POLLING ON LOW BATTERY. ↝ REDUCE ANIMATION

    FREQUENCY. ↝ STOP PREFETCHING BUNDLES. ↝ PERSIST UNSAVED DATA BEFORE SHUTDOWN RISK. ↝ SWITCH TO A STATIC MAP RATHER THAN AN INTERACTIVE ONE. BATTERY STATUS: IDEAS
  261. COMPUTE PRESSURE: OVERVIEW const observer = new PressureObserver(records = >

    { const state = records[0].state; if (state === "critical") { reduceRenderingQuality(); } }); observer.observe("cpu", { sampleInterval: 2000 });
  262. ↝ LOWER CANVAS RESOLUTION DYNAMICALLY. ↝ PAUSE BACKGROUND DATA PROCESSING

    PIPELINES. ↝ SWITCH FROM REAL-TIME UPDATES TO BATCHED ONES. ↝ DROP FRAME RATE IN WEBGL SCENES. ↝ REDUCE ANIMATION QUALITY WHEN CPU PRESSURE RISES. COMPUTE PRESSURE: IDEAS
  263. PAGE VISIBILITY: OVERVIEW document.hidden; document.visibilityState; document.addEventListener("visibilitychange", () = > {

    if (document.visibilityState===“hidden") { console.log("This window is hidden") } else { console.log("This window is visible") } })
  264. ↝ CANCEL POLLING LOOPS, TIMERS, AND BACKGROUND NETWORK REFRESHES WHEN

    THE TAB BECOMES HIDDEN. ↝ PAUSE VIDEO, AUDIO, AND ANIMATION LOOPS WHEN THE USER ISN’T ACTIVELY WATCHING THE PAGE. ↝ RESUME PROGRESSIVE DOWNLOADS OR DYNAMIC IMPORTS WHEN THE PAGE BECOMES VISIBLE AGAIN. PAGE VISIBILITY: IDEAS
  265. ↝ STOP REFRESHING DASHBOARDS OR LIVE DATA FEEDS WHILE THE

    TAB IS BACKGROUNDED. ↝ SEND ANALYTICS RELIABLY AT SESSION END WHEN VISIBILITY BECOMES HIDDEN. ↝ SILENCE NOTIFICATIONS OR SOUNDS WHEN THE DEVICE SCREEN LOCKS OR THE TAB LOSES VISIBILITY. PAGE VISIBILITY: IDEAS
  266. INTERSECTION OBSERVER: OVERVIEW const onIntersection = (entries) = > {

    for (const entry of entries) { if (entry.isIntersecting) { console.log(entry); } } }; const observer = new IntersectionObserver(onIntersection); observer.observe(document.querySelector('#target'));
  267. ↝ INITIALIZE EXPENSIVE RENDERING PIPELINES (CHARTS, CANVAS, WEBGL) ONLY WHEN

    NEEDED. ↝ LAZY-LOAD IMAGES, IFRAMES, AND ROUTE BUNDLES WHEN THEY APPROACH THE VIEWPORT. ↝ DELAY LOADING THIRD-PARTY WIDGETS (MAPS, VIDEO EMBEDS, CHAT CLIENTS) UNTIL VISIBLE. ↝ CONTROL MEDIA PLAYBACK DEPENDING ON VISIBILITY. INTERSECTION OBSERVER: IDEAS
  268. ↝ RENDER/HYDRATE COMPLEX UI COMPONENTS ONLY WHEN THEY BECOME RELEVANT.

    ↝ TRIGGER ANALYTICS EVENTS WHEN USERS ACTUALLY SEE IMPORTANT UI SECTIONS. ↝ MEASURE HOW LONG ELEMENTS REMAIN VISIBLE (E.G., AD IMPRESSIONS). INTERSECTION OBSERVER: IDEAS
  269. ↝ MANY WEBSITES HAVE DOM ELEMENTS SHIFTING AROUND DUE TO

    CONTENT LOADING ASYNCHRONOUSLY. ↝ MEASURE REAL CLS VALUES IN PRODUCTION. ↝ IDENTIFY THE EXACT DOM ELEMENTS RESPONSIBLE FOR LAYOUT INSTABILITY. ↝ IGNORE EXPECTED SHIFTS CAUSED BY USER INTERACTION. LAYOUT INSTABILITY: OVERVIEW
  270. LAYOUT INSTABILITY: OVERVIEW let cls = 0; new PerformanceObserver((list) =

    > { for (const entry of list.getEntries()) { if (entry.hadRecentInput) continue; / / ignore expected shifts cls += entry.value; const culprit = entry.sources?.[0]?.node; console.log("Shift:", entry.value); console.log("Element:", culprit); console.log("CLS so far:", cls); } }).observe({ type: "layout-shift", buffered: true });
  271. ↝ DETECT INSTABILITY INTRODUCED BY THIRD-PARTY EMBEDS OR PERSONALIZATION. ↝

    DETECT IMAGES OR IFRAMES LOADING WITHOUT A RESERVED SPACE. ↝ DETECT LAYOUT SHIFTS CAUSED BY WEB-FONT SWAPS. LAYOUT INSTABILITY: IDEAS
  272. #protip 💡 Existing RUM and DXA tools are great—until scale,

    cost, or product-speci fi c questions force you to measure things yourself.
  273. TIME UNTIL THE… ↝ SCROLL EFFECTS WORK. ↝ APP RESPONDS

    TO CLICKS. ↝ MOST MEANINGFUL VIDEOS/ANIMATIONS RUN. ↝ PRIMARY FEATURE SHOWS UP/IS INTERACTIVE. ↝ COOKIE BANNER SHOWS UP. PRODUCT-SPECIFIC QUESTIONS
  274. ↝ REACT COMPILER FORGET ↝ ACTIVITY OFFSCREEN ↝ OPTIMISTIC STATE

    UPDATES ↝ RESOURCE PRELOADING ↝ TRANSITION TRACING ↝ … THE PRESENT FUTURE
  275. ↝ RENDERING IN THE BACKGROUND WITH NO ADDITIONAL PERFORMANCE OVERHEAD.

    ↝ IT DOESN'T MOUNT UNTIL THE COMPONENT BECOMES VISIBLE AND ITS EFFECTS ARE NOT FIRED. ↝ TOGGLE THE VISIBILITY WITHOUT LOSING THE STATE. ↝ INTEGRATED INTO ROUTERS AND OTHER UI LIBRARIES. OFFSCREEN ACTIVITY
  276. ↝ ROUTERS CAN PRE-RENDER SCREENS IN THE BACKGROUND SO THAT

    THEY’RE INSTANTLY AVAILABLE. ↝ TAB SWITCHING CAN PRESERVE THE STATE OF HIDDEN TABS, SO THE USER CAN SWITCH BETWEEN THEM WITHOUT LOSING THEIR PROGRESS. ↝ A VIRTUALIZED LIST CAN PRERENDER ADDITIONAL ROWS ABOVE AND BELOW THE VISIBLE WINDOW. OFFSCREEN ACTIVITY
  277. SUSPENSE FOR CPU-BOUND TREES ↝ FORCES A FALLBACK ON THE

    INITIAL RENDER REGARDLESS OF WHETHER SOMETHING IS SUSPENDED. ↝ DURING THE INITIAL MOUNT, REACT WILL SKIP OVER EXPENSIVE TREES BY RENDERING A PLACEHOLDER. ↝ IT HELPS UNBLOCK THE INITIAL SKELETON FOR THE NEW SCREEN.
  278. CODE EXTRACTION import json from "./foo.json" with { type: "json"

    }; import ComponentA from "./A" with { type: "client" } import ComponentB from "./B" with { type: "both" }
  279. WHY SOMETHING IS THE FUTURE ROUTING MPAs vs. SPAs CODE

    EXTRACTION OKB JAVASCRIPT REACTIVITY HYDRATION COMPILERS
  280. React is a spreading agent for Computer Science in our

    realm. DSLs, COMPILERS, CONCURRENCY, FIBERS, EFFECT HANDLERS, IMMUTABILITY… OH MY! #2 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  281. React tries to address the lack of some JavaScript/Web Platform

    resources. #3 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  282. Understanding these internals and their rationales helps us implement our

    own abstractions. #4 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  283. OUR OWN ABSTRACTIONS… ↝ INTERNAL SUSPENSE-READY SOLUTIONS (E.G. FIRST CLASS

    SUPPORT FOR PROMISES). ↝ GENERATOR-BASED SCHEDULER. ↝ CUSTOM MEMORY MANAGEMENT. ↝ CUSTOM METRICS (E.G. DXA, JQUERY TRACKING). ↝ STATIC-ANALYSIS-ENABLED WORKFLOWS.
  284. AI agents can write React. But engineers who understand scheduling,

    rendering, and data- fl ow boundaries can decide what should be optimized. #5 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  285. Internals matter more in the AI era. Compilers automate optimizations.

    Agents automate code. Only engineers understand tradeo ff s. #5 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  286. React stopped being just a library years ago. AND WE’RE

    STILL CATCHING UP TO WHAT IT BECAME… ↝ COMPILER TARGET? ↝ RUNTIME SCHEDULER? ↝ SERVER-FIRST PLATFORM? #6 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  287. Core Web Vitals are a better starting point than a

    fi nish line. #7 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS — IN THE BLINK OF AN EYE • TIM KADLEC , 2024
  288. There's no silver bullet. Identify your core metrics. #8 REACT:

    INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  289. #9 Always try to correlate behavior analysis with contextual metrics

    and business outcomes to tell the full story. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  290. LCP ⁵ RETENTION RATE — CORE WEB VITALS AND THEIR EFFECT

    ON USER EXPERIENCE • PHILIP TELLIS, 2025
  291. CLS ⁵ RELOAD RATE — CORE WEB VITALS AND THEIR EFFECT

    ON USER EXPERIENCE • PHILIP TELLIS, 2025
  292. INP ⁵ RAGE CLICK RATE — CORE WEB VITALS AND THEIR

    EFFECT ON USER EXPERIENCE • PHILIP TELLIS, 2025
  293. #10 Don't take fast networks, CPUs and RAM for granted.

    REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS
  294. There's probably a business case for making your app faster.

    But web performance is about more than “just” business. #11 REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS