A presentation at #PerfMatters by Vasanth Krishnamoorthy
Turbocharging Walmart.com: Speed without compromise Vasanth Krishnamoorthy vasanth_k vasanthk
Focus Areas Approaching Performance 7 Key Optimizations Guardrails for Performance
100 million+ customers per month Over 30% growth YoY
Performance as a Measure Of User Happiness
Typical Customer Journey Cart Checkout Product Home Page Page Search Tech Stack
Customer Journey 42% Improvement TTI - 95th %ile mobile web
PART 1 Approaching Performance
Where do you start?
“You can’t improve what you don’t measure”
Measure What Matters TTI – Time to interactive (custom) TTFB – Time to first byte TLOAD - Page is fully loaded (custom) TTFB TTI TLOAD
Define Your Scope
Define Your Scope & Constraints 01 02 03 No compromise to existing product features No slowdown on new product features being built No big rewrites or tech stack changes
Identify The Right Opportunities
Empathize With Your Users Understand common user flows Revenue distribution by browsers & platform Step progression User distribution by browsers/devices/connection Use data to understand user pain points
Audit Your Application Chrome’s Dev Tools WebPageTest & Lighthouse Make the invisible visible Webpack Bundle Analyzer
Apply First Principles
Principles of Web Performance 1 Do only what is needed 2 Minimize round trip time 3 Optimize Perceived Performance
PART 2 7 Key Optimizations
Do only what is needed
Reduce Bundle Size
1 Code Splitting & Lazy Loading “Get it when you need it” Component centric code splitting via dynamic imports (ES2020) TTI 18.2% Code split user/item specific feature code Lazy load components which are below the fold 18.2% Cumulative TTI Improvement
1 Code Splitting - Learnings Aggressive code splitting increased overall bytes downloaded Our sweet spot Duplicates in chunks Reduced Compression 18.2% Cumulative TTI Improvement < 15 split bundles
2 Slim Down Libraries Gains From Switch To Moment.js date-fns 50KB React v15 React v16 15KB React-Intl Custom utility 14KB Recompose React API / Hooks 5KB (compressed) Upgrade from Webpack v3 to v4 reduced bundle size by 10% TTI 9.7% 18.2% 26.1% Cumulative TTI Improvement
3 Differential Serving Enables us to serve modern JS code to users Why do we need it? TTI 3.3% • Transformed ES5 code is verbose (more KB) • Cut down on polyfills needed (~35KB for us) 28.5% 26.1% Cumulative TTI Improvement
3 Differential Serving Module No-Module Pattern 28.5% 26.1% Cumulative TTI Improvement
3 Differential Serving - Learnings Problem On a few browser versions both ES5 & ES6 scripts were downloaded/executed leading to degraded experience for those customers 28.5% 26.1% Cumulative TTI Improvement
3 Differential Serving - Learnings Solution On Server side, we check for the user agent passed and depending on whether the browser supports modern syntax or not we include the right bundle into the page. 28.5% 26.1% Cumulative TTI Improvement
Minimize round trip time
Sharing is caring for our users
4 Shared Bundles Webpack DLL Plugin 1P/3P bundles • Shared across whole site Functional shared bundles • Shared across Cart & Checkout TTI 10.2% 35.8% 25.8% Cumulative TTI Improvement
4 Shared Bundles - Learnings Functional shared bundles 1P/3P shared bundle Needs unification of package versions across applications Updates frequently and requires changes across all shared web-apps Updates to shared bundles require coordination with multiple teams Testing/validations & Release effort 35.8% 28.5% Cumulative TTI Improvement
5 Shared Header/Footer Problem Header/Footer package was bundled into each app leading to bloat Any change required testing/validation & deployments across for all teams
5 Shared Header/Footer Render Header/Footer & rest of the App in parallel during SSR Solution Endpoint returning header/footer HTML Fragment Markup & bundles get cached
5 Shared Header/Footer 70% Optimization reduction in client side JS Reuse existing code and render with React on Server Side TTI 8.1% Use Vanilla JS for handling events on client 41% 35.8% Cumulative TTI improvement
6 Brotli Compression “It’s like GZIP on steroids” 12% smaller bundles than GZIP TTI 9.8% 46.7% 41% Cumulative TTI Improvement
6 Brotli Compression – Learnings Dynamic compression can be slow For Best Perf - Pre-build compressed assets and serve it from a CDN to save the runtime cost. 46.7% 41% Cumulative TTI Improvement
6 Brotli Compression - Learnings For Differential Serving Brotli compressed ES5 bundles pretty well ES6 vs ES5 bundle difference dropped from 10% to 4%* *YMMV 46.7% 41% Cumulative TTI Improvement
Optimize Perceived Performance
7 Leverage Priorities & Resource Hints <script> <script async> defer> HTML parsing Script download HTML parsing paused Script execution TTI 5.7% 49.7% 46.7% Cumulative TTI improvement
7 Leverage Priorities & Resource Hints Tells the browser to download and cache a resource to have them available for execution when it is needed 49.7% 46.7% Cumulative TTI Improvement
7 Leverage Priorities & Resource Hints dns-prefetch preconnect DNS lookup DNS lookup, TLS negotiation, and TCP handshake 49.7% 46.7% Cumulative TTI Improvement
Can we make it faster?
“The fastest HTTP request is the one not made”
8 Prefetch Downloads scripts with lower priority & stores it in prefetch cache TTI 12.1% Cached for at least 5mins Does not execute JS 49.7% 55.8% Cumulative TTI Improvement
8 Prefetch - Learnings Workaround Problem Impacts current page’s load times • We include prefetch tags into the page after onLoad event is fired • We do not prefetch if the user has data saver on 49.7% 55.8% Cumulative TTI Improvement
Video Comparison Before After
Key Takeaways
Perf Optimizations – Key Takeaways Reduce Bundle Size • Code Splitting & Lazy Loading • Slim down libraries • Differential Serving Shared bundles • 1P/3P & functional shared bundles • Header/Footer HTML fragment Font Optimization • Remove unused glyphs & styles • WOFF & WOFF2 for better compression Image • • • Lazy load images WEBP SVG Better compression • Brotli Redux State transfer optimization • Send state to client in an inert tag Priorities & resource hints • Prefer defer over async • dns-prefetch & preconnect • Prefetch Other Cleanup • Code which you have always wanted to delete. You know what they are J 55.8% 60% Cumulative TTI Improvement
Perf Improvements Over Time TTI What you think it was What it actually was Time (months)
Challenges Performance Regressions Time to complete A/B Tests 3rd Party Scripts: Ads, Marketing Tags Cross-team initiatives
PART 3 Guardrails For Performance
Performance Budgets TTFB Speed Index TTI Page Complete
Performance Metrics Per PR Bundle Size check at PR
Performance Metrics Per PR Lighthouse metrics for each PR View perf metrics over time
Compare Metrics Across Branches Teams can compare branch performance to production performance Click through commits and see what caused the degradation Results used to accept or reject release
Sustaining A Performance Culture Embed performance thinking early in the product development process Use tooling and data to help drive decisions on performance tradeoffs Maintain gains by monitoring key metrics, tooling and having guardrails Recognize performance is hard and there will be tradeoffs
The Team Bryan Morgan Denys Mikhalenko Cory Dang Ah Hyun Cho Hiren Patel Madhav Deverkonda Test Armada & Torbit Team Gauri Shankar Rodrigo Delgado Jon Campbell Uma Mahesh Meet Parikh Megha Gupta Patrick Stapleton Vijay Muniswamy
Future Plans 01 Progressive Web App (PWA) 02 Experimenting with alternative UI libraries 03 Streaming SSR 04 Different experiences based on Speed Profiles
Performance Is A Journey, Not A Destination
THANK YOU vasanth_k vasanthk
eCommerce market is highly competitive and site speed plays a major role in improving overall buying experience and fulfilling user needs. In most companies there is always a constant push and pull towards spending time adding new features vs improving performance. There are also constraints around 3rd party integrations, ads & making changes happen across various teams can also be a challenge. In this talk we’re going to look into ways by which you can smartly improve performance without cutting down on features and without changing much of the user’s experience. We’ll talk about different modern techniques that helped improve Walmart.com’s and how understanding user behavior can go a long way in optimizing performance.