Question presented to candidate: "An app feels slow. How do you approach making it faster?"
What a strong answer should cover:
- Measure before changing anything, and measure the right thing: Lighthouse and Core Web Vitals for load, the DevTools Profiler for interaction, the Network panel for data.
- The categories are distinct and easily confused: load performance, network, render performance, and memory.
- Load: code splitting with
React.lazyat route boundaries, tree shaking, checking the bundle for accidentally-included heavy dependencies, and server rendering for first paint. - Network: eliminating waterfalls with
Promise.alland loaders, caching with a query library, and preloading. - Render: structural fixes first (move state down, lift content up), then memoisation, then context splitting.
- Lists: virtualisation, which is a different order of magnitude from memoisation.
- Concurrent features:
useTransitionanduseDeferredValueto keep input responsive during expensive updates — perceived performance rather than less work. - Images and fonts are frequently the real problem and have nothing to do with React.
- Know which metric you are moving: LCP, INP, and CLS measure different things.
Clarifying questions expected:
- "Slow to load, or slow to interact? Those are completely different problems."
- "Do we have real user metrics, or is this anecdotal?"
- "Which device and network are we targeting?"
Code / implementation expected: Optional — route-level code splitting and a transition are the two most demonstrable.