Slide 1

Slide 1 text

مالس, React Africa! 👋 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE • NOVEMBER 29, 2024.

Slide 2

Slide 2 text

MATHEUS ALBUQUERQUE • @ythecombinator SPEED AT SCALE OPTIMIZING THE LARGEST CX PLATFORM OUT THERE

Slide 3

Slide 3 text

Matheus Albuquerque ↝ 👨💻 Staff SWE @ Medallia ↝ ⚡ Google Developer Expert ↝ 𝕏 ythecombinator

Slide 4

Slide 4 text

Preamble SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 5

Slide 5 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / PREAMBLE

Slide 6

Slide 6 text

[…] “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 stuff.” […] — The silent majority, by Vadim Kravcenko

Slide 7

Slide 7 text

[…] “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, by Vadim Kravcenko

Slide 8

Slide 8 text

This talk is not about… ↝ React 19, Svelte 5, Vue 3… ↝ ISG, SSR, Streaming SSR… ↝ Progressive/Selective/Partial Hydration… ↝ Islands Architecture, Resumability…

Slide 9

Slide 9 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / PREAMBLE

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

— MEDALLIA SURVEYS • MARIZ MELO

Slide 14

Slide 14 text

This talk is about… ↝ Modernizing Dependencies ↝ Code Splitting ↝ Preact ↝ Targeting Different Browsers

Slide 15

Slide 15 text

This talk is also about… ↝ Challenges in Legacy Codebases ↝ Experiences ↝ Our Radar ↝ Lessons Learned

Slide 16

Slide 16 text

Act I: Modernizing Dependencies SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 17

Slide 17 text

BEFORE…

Slide 18

Slide 18 text

WEBPACK 1 ↝ 5 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 19

Slide 19 text

WEBPACK 1 ↝ 5

Slide 20

Slide 20 text

WEBPACK 1 ↝ 5

Slide 21

Slide 21 text

↝ MIGRATION IS ABOUT HAVING ALL THE PLUGINS AND LOADERS ON THEIR LATEST VERSIONS AND ENSURING THEY'RE COMPATIBLE WITH EACH OTHER. ↝ V5 MIGRATION CAN'T BE DONE FROM V2/V3. THAT’S AN ENTIRELY DIFFERENT PROCESS. ↝ NODE 10.13.0 IS THE MINIMUM REQUIREMENT FOR V5 BUT SOME PLUGINS/LOADERS REQUIRE HIGHER VERSIONS. WEBPACK 1 ↝ 5: GOTCHAS

Slide 22

Slide 22 text

NODE 10 ↝ 16 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 23

Slide 23 text

NODE 10 ↝ 16

Slide 24

Slide 24 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES / NODE

Slide 25

Slide 25 text

REACT 15 ↝ 16 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 26

Slide 26 text

REACT 15 ↝ 16

Slide 27

Slide 27 text

REACT 15 ↝ 16

Slide 28

Slide 28 text

REACT 15 㱺 16

Slide 29

Slide 29 text

❌ REACT 15 㱺 16

Slide 30

Slide 30 text

REACT 15 㱺 16

Slide 31

Slide 31 text

❌ REACT 15 㱺 16

Slide 32

Slide 32 text

REACT 15 ↝ 16

Slide 33

Slide 33 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES / REACT

Slide 34

Slide 34 text

#definition 🧐 Jscodeshift is a tool that runs a transformation script over one or more JavaScript or TypeScript files.

Slide 35

Slide 35 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES / REACT

Slide 36

Slide 36 text

REACT 15 ↝ 16

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

CODEGEN: OVERVIEW SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 39

Slide 39 text

WE HAD TO SUPPORT, IN PARALLEL: ↝ DIFFERENT VERSIONS OF DEVELOPER DEPENDENCIES (E.G. node.js, Webpack, Babel, ETC.) ↝ DIFFERENT VERSIONS OF APPLICATION DEPENDENCIES (E.G. React ITSELF) ↝ DIFFERENT STRATEGIES USED FOR BUNDLING AND SERVING CODEGEN: OVERVIEW

Slide 40

Slide 40 text

CODEGEN: BEFORE REPO / PACKAGES / A (CORE) B (FUNCTIONAL TESTS) …

Slide 41

Slide 41 text

CODEGEN: AFTER REPO / PACKAGES / (LEGACY) A (LEGACY) B NEXT GENERATION (CONFIG + SCRIPTS)* NEXT GENERATION (CODE GENERATED) …

Slide 42

Slide 42 text

CODEGEN: AFTER REPO / PACKAGES / (LEGACY) A (LEGACY) B NEXT (CONFIG + SCRIPTS)* NEXT (CODE GENERATED) … ↝ DEFAULT BUNDLE THAT’S SERVED. ↝ ACTIVE DEVELOPMENT (IE. NEW FEATURES/FIXES) HAPPENS HERE. ↝ THIS IS THE CODE THAT’S PUSHED TO THE REPO. ↝ LEGACY DEPENDENCIES: REACT 15, WEBPACK 1, NODE 10, ETC.

Slide 43

Slide 43 text

CODEGEN: AFTER REPO / PACKAGES / (LEGACY) A (LEGACY) B NEXT (CONFIG + SCRIPTS)* NEXT (CODE GENERATED) … ↝ HIDDEN BEHIND A FEATURE FLAG. ↝ MODERN DEPENDENCIES: REACT 16, WEBPACK 5, NODE 18, ETC. ↝ MOSTLY COMPOSED OF CODE TRANSFORMERS, AUTOMATION SCRIPTS, AND WEBPACK/BABEL CONFIG. ↝ ALSO, PARTS OF THE CODE THAT CAN'T BE CODE GENERATED (IE. UNIT AND FUNCTIONAL TESTS).

Slide 44

Slide 44 text

CODEGEN: AFTER REPO / PACKAGES / (LEGACY) A (LEGACY) B NEXT (CONFIG + SCRIPTS)* NEXT (CODE GENERATED) … ↝ GENERATED AT BUILD TIME (IE. CI/LOCALLY). ↝ REACT COMPONENTS, UTILS, AND OTHER BUSINESS LOGIC. ↝ THIS CODE IS NEVER PUSHED (1K+ LINES IN GITIGNORE FILE).

Slide 45

Slide 45 text

CODEGEN: AFTER

Slide 46

Slide 46 text

CODEGEN: TRANSFORMERS SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 47

Slide 47 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES / CODEGEN: TRANSFORMERS

Slide 48

Slide 48 text

CODEGEN: AST

Slide 49

Slide 49 text

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(); } CODEGEN: BASIC TRANSFORMER

Slide 50

Slide 50 text

CODEGEN: TRANSFORMER GROUPS const transformGroups = [ { label: "PropTypes → prop-types", pattern: "./src/ * /.{js,jsx}", transformerPath: proptypes, }, { label: "legacy-testing/src/testUtils → ./utils/test", pattern: "./src/ * /.jsx", transformerPath: testUtils, }, { label: " * .scss → * .global.scss", pattern: "./src/ * /.jsx", transformerPath: cssGlobals, }, ];

Slide 51

Slide 51 text

for (const item of transformGroups) { logger.info(`\n🛠 Appying the '${item.label}' transform`); await applyTransformer(item.transformerPath, item.pattern); } CODEGEN: RUNNING

Slide 52

Slide 52 text

WEBDRIVER 4 ↝ 7 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 53

Slide 53 text

WEBDRIVER 4 ↝ 7

Slide 54

Slide 54 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / MODERNIZING DEPENDENCIES /

Slide 55

Slide 55 text

jscodeshift -t ./node_modules/@wdio/codemod/v6 ./wdio.conf.js jscodeshift -t ./node_modules/@wdio/codemod/v6 ./src/e2e/ *

Slide 56

Slide 56 text

WEBDRIVER 4 ↝ 7: GOTCHAS

Slide 57

Slide 57 text

WEBDRIVER 4 ↝ 7: GOTCHAS 🤔 🤔 🤔

Slide 58

Slide 58 text

WEBDRIVER 4 ↝ 7: GOTCHAS

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Act II: Code Splitting SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 61

Slide 61 text

CODE SPLITTING — HTTPS://WWW.PATTERNS.DEV

Slide 62

Slide 62 text

CODE SPLITTING: REACT

Slide 63

Slide 63 text

CODE SPLITTING: RESULTS

Slide 64

Slide 64 text

CODE SPLITTING: RESULTS

Slide 65

Slide 65 text

#protip 💡 Dynamic imports are a great tool but, like all optimizations, they don’t come for free.

Slide 66

Slide 66 text

CODE SPLITTING: GOTCHAS

Slide 67

Slide 67 text

Act III: Preact SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 68

Slide 68 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / PREACT

Slide 69

Slide 69 text

PREACT 42.4KB (MIN+GZIP) 4KB (MIN+GZIP)

Slide 70

Slide 70 text

PREACT 205.9KB MIN + GZIP / NO POLYFILLS 175.26KB MIN + GZIP / NO POLYFILLS

Slide 71

Slide 71 text

PREACT: GOTCHAS

Slide 72

Slide 72 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / PREACT

Slide 73

Slide 73 text

Act IV: jQuery SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 74

Slide 74 text

JQUERY: OVERVIEW

Slide 75

Slide 75 text

JQUERY: OVERVIEW — BASICS OF THE G2 + MEDALLIA INTEGRATION • G2 DOCUMENTATION

Slide 76

Slide 76 text

JQUERY: ISSUES

Slide 77

Slide 77 text

JQUERY: DETECTING / BUILD-TIME

Slide 78

Slide 78 text

JQUERY: DETECTING / BUILD-TIME

Slide 79

Slide 79 text

JQUERY: DETECTING / BUILD-TIME

Slide 80

Slide 80 text

JQUERY: DETECTING / RUNTIME

Slide 81

Slide 81 text

JQUERY: DETECTING / RUNTIME

Slide 82

Slide 82 text

JQUERY: CONVERTING

Slide 83

Slide 83 text

Act V: Targeting Different Browsers SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 84

Slide 84 text

WHICH BROWSERS ARE VISITING OUR APP? SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS

Slide 85

Slide 85 text

POLYFILLING: CONCERNS

Slide 86

Slide 86 text

STRATEGIES SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS /

Slide 87

Slide 87 text

#1 of 3 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES polyfill.io

Slide 88

Slide 88 text

polyfill.io ↝ INSPECTS THE BROWSER’S USER-AGENT AND SERVES A SCRIPT WITH POLYFILLS TARGETED AT THAT BROWSER. ↝ SUPPORTS PICKING A SUBSET OF POLYFILLS (E.G. Map). ↝ THE BROWSER WILL HAVE TO SPEND EXTRA 50-300 MS TO SETUP A CONNECTION. ↝ SUBJECT TO polyfill.io OUTAGE.

Slide 89

Slide 89 text

polyfill.io

Slide 90

Slide 90 text

#2 of 3 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES BABEL PRESET

Slide 91

Slide 91 text

↝ NOT VERY USEFUL IF YOU’RE TARGETING OLD BROWSERS (E.G. IE 11). ↝ IT MIGHT REMOVE SOME POLYFILLS, BUT MOST OF THEM WILL STAY IN THE BUNDLE AND WOULD STILL BE DOWNLOADED BY EVERYONE. useBuiltIns: entry

Slide 92

Slide 92 text

useBuiltIns: usage ↝ IT DOESN'T ADD POLYFILLS FOR DEPENDENCIES* ↝ YOU MIGHT GET RUNTIME ERRORS IN LEGACY BROWSERS ↝ IT MIGHT ALSO ADD EXCESSIVE POLYFILLS, E.G. • Array.includes AND String.includes • Symbol.toStringTag, Math.toStringTag, ETC.

Slide 93

Slide 93 text

#3 of 3 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES DIFFERENTIAL SERVING

Slide 94

Slide 94 text

↝ NO ES6 SUPPORT = WON'T LOAD type="module" SCRIPTS AND WILL LOAD nomodule ONES. ↝ YOU CAN USE nomodule TO SERVE ES6 POLYFILLS TO BROWSERS THAT NEED THEM. DIFFERENTIAL SERVING

Slide 95

Slide 95 text

DIFFERENTIAL SERVING

Slide 96

Slide 96 text

SUMMING UP… ↝ 1⃣ POLYFILL.IO: EASY AND DOESN’T SHIP ANYTHING TO MODERN BROWSERS. MIGHT INCREMENT TTI AND FCP. ↝ 2⃣ useBuiltIns: EASY TO SETUP BUT EITHER NOT VERY USEFUL FOR OLDER BROWSERS, OR REQUIRES YOU TO COMPILE node_modules AS WELL. ↝ 3⃣ module/nomodule: EASY AND WIDE SUPPORT BUT ONLY STRIPS ES6−POLYFILLS.

Slide 97

Slide 97 text

#1 of 3 RAW MODULE/NOMODULE — WHAT IS DIFFERENTIAL SERVING? • JOHN STEWART SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES

Slide 98

Slide 98 text

#1 of 3 ↝ DOWNLOADS BOTH BUNDLES AND EXECUTES BOTH BUNDLES. ↝ DOWNLOADS BOTH BUNDLES. ↝ DOWNLOADS LEGACY BUNDLE AND DOWNLOADS ESM BUNDLE TWICE. RAW MODULE/NOMODULE — WHAT IS DIFFERENTIAL SERVING? • JOHN STEWART SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES

Slide 99

Slide 99 text

#2 of 3 USER AGENT DETECTION — SMART BUNDLING • SHUBHAM KANODIA SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES

Slide 100

Slide 100 text

#2 of 3 ↝ YOU MIGHT NOT BE IN CONTROL OF THE SERVER. ↝ IF YOU LOAD A MODERN SCRIPT WITHOUT THE MODULE ATTRIBUTE, YOU LOSE STREAM PARSING AND OFF MAIN THREAD COMPILATION. USER AGENT DETECTION SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES

Slide 101

Slide 101 text

#3 of 3 RUNTIME DETECTION var script = document.createElement('script'); var prefix = (!('noModule' in check)) ? "/ie11" : "/esm"; script.src = prefix + "/index.js"; document.head.appendChild(script); SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / TARGETING DIFFERENT BROWSERS / STRATEGIES

Slide 102

Slide 102 text

SUMMING UP… POLYFILL.IO useBuiltIns module/nomodule POLYFILLING RAW module/nomodule USER AGENT DETECTION RUNTIME DETECTION SERVING

Slide 103

Slide 103 text

Results SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 104

Slide 104 text

PULL REQUESTS

Slide 105

Slide 105 text

UNIT TESTS

Slide 106

Slide 106 text

BUNDLE FOOTPRINT ˜37% SMALLER BUNDLE FOOTPRINT ON MODERN BROWSERS: 279.15 KB → 176.78 KB MODERN ˜25% SMALLER BUNDLE FOOTPRINT ON LEGACY BROWSERS 279.15 KB → 223.1 KB LEGACY

Slide 107

Slide 107 text

BUNDLE FOOTPRINT BROWSERS THAT SUPPORT ES MODULES AND HAPPEN NOT TO NEED EXTRA POLYFILLS. AS OF SEPTEMBER 21, 2024, THESE REPRESENT 95.93% OF THE GLOBAL USAGE. MODERN BROWSERS THAT DON’T FIT THE PREVIOUS CRITERIA. MOSTLY THOSE ARE PRE-2018 BROWSERS WITH INTERNET EXPLORER BEING THE HIGHLIGHT. LEGACY

Slide 108

Slide 108 text

BROWSER LINE ↝ 0.2% INTERNET EXPLORER USAGE ↝ NO OTHER BROWSERS WILL DOWNLOAD THE LARGE BUNDLE

Slide 109

Slide 109 text

↝ FCP: 6S FASTER ↝ SPEED INDEX: 3.5S FASTER ↝ LCP: 2.4S FASTER ↝ TTI: 2S FASTER CORE WEB VITALS ⬇

Slide 110

Slide 110 text

TIMINGS VISUALLY COMPLETE LAST VISUAL CHANGE LOAD TIME (ONLOAD) LOAD TIME (FULLY LOADED) DOM CONTENT LOADED FEATURE FLAG ON FEATURE FLAG OFF — WEBPAGETEST

Slide 111

Slide 111 text

VISUAL PROGRESS FEATURE FLAG ON FEATURE FLAG OFF — WEBPAGETEST

Slide 112

Slide 112 text

Our Radar SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 113

Slide 113 text

CULTURE + TOOLING

Slide 114

Slide 114 text

CULTURE + TOOLING

Slide 115

Slide 115 text

CULTURE + TOOLING

Slide 116

Slide 116 text

COMPRESSION

Slide 117

Slide 117 text

QUIC — A QUIC UPDATE ON GOOGLE’S EXPERIMENTAL TRANSPORT • CHROMIUM BLOG

Slide 118

Slide 118 text

Closing Thoughts SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE /

Slide 119

Slide 119 text

#1 of 5 SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS UNDERSTANDING INTERNALS HELPS US IMPLEMENT OUR OWN ABSTRACTIONS. E.G. THE JSCODESHIFT-BASED ARCHITECTURE UPGRADE & THE BABEL-BASED MIGRATION TOOLS.

Slide 120

Slide 120 text

COMPILERS & UI ENGINEERING

Slide 121

Slide 121 text

COMPILERS & UI ENGINEERING

Slide 122

Slide 122 text

COMPILERS & UI ENGINEERING

Slide 123

Slide 123 text

COMPILERS & UI ENGINEERING

Slide 124

Slide 124 text

#2 of 5 YOU HAVE TO SHIP POLYFILLS TO ALL BROWSERS YOUR USERS MIGHT USE… . . . BUT IT'S A BAD IDEA TO SHIP ALL THEORETICALLY REQUIRED POLYFILLS TO ALL OF THEM! SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS

Slide 125

Slide 125 text

#3 of 5 DON'T TAKE FAST NETWORKS, CPUS AND RAM FOR GRANTED. TEST ON REAL PHONES AND NETWORKS. SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS

Slide 126

Slide 126 text

SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS

Slide 127

Slide 127 text

#4 of 5 THERE'S NO SILVER BULLET. IDENTIFY YOUR CORE METRICS. SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS

Slide 128

Slide 128 text

#5 of 5 ALWAYS TRY TO CORRELATE BUSINESS METRICS WITH PERFORMANCE METRICS. THERE IS NO WAY TO GAME THESE BECAUSE THEY DEPEND ON THE BEHAVIOR OF REAL USERS. SPEED AT SCALE: OPTIMIZING THE LARGEST CX PLATFORM OUT THERE / CLOSING THOUGHTS

Slide 129

Slide 129 text

THAT’S ALL, FOLKS! THANKS! 👋 QUESTIONS? MATHEUS ALBUQUERQUE • @ythecombinator ⬆ ALL THE LINKS!