Performance
508 bites tagged Performance — interview questions with model answers, and 60-second explainers.
Tree Shaking: Shipping Only the Code You Use
Tree shaking is a build step that eliminates unused code from your final bundle. Bundlers like webpack use it to shrink JavaScript files by removing functions you import but never call.
Bundle Analysis: An X-Ray for Your App's Weight
Bundle analysis is an X-ray for your compiled JavaScript, showing which libraries contribute to your app's final size. Use it to diagnose slow loads by finding large or duplicated dependencies. The footgun: focus on gzipped size, not raw size.
List Virtualization: Render the Window, Not the World
Virtualization renders only the visible "window" of a long list, not the entire dataset. It's essential for performance in feeds or tables with thousands of rows.
React DevTools Profiler: Find Performance Bottlenecks
The React Profiler records how long components take to render, helping you find performance bottlenecks. Use it to diagnose slow interactions and see which components re-render too often.
React.lazy: Load Components On Demand
React.lazy tells your app: "Don't download this component's code until it's needed." It's a core tool for code splitting. Use it for below-the-fold content or modals to speed up initial load. The footgun: forgetting `<Suspense>` will crash your app.
React.memo: Skip Unnecessary Component Renders
React.memo tells a component to skip re-rendering if its props are the same as last time. Use it to prevent costly renders when a parent updates. The footgun is passing new objects or functions as props, which breaks the default shallow comparison.
Debouncing vs. Throttling in React
Debouncing waits for a pause in events before acting; throttling fires at a steady rate. Use debounce for search bars to avoid API calls on every keystroke, and throttle for scroll handlers to prevent lag.
React Hook Form: Faster Forms with Less Code
React Hook Form builds performant forms by using uncontrolled inputs, avoiding re-renders on every keystroke. It's ideal for complex forms where managing state with `useState` becomes slow. The main footgun: overuse of `watch()` can negate performance gains.
useDeferredValue: Keep UI Responsive During Renders
useDeferredValue keeps your UI responsive by showing a stale value while a new, expensive-to-render value is prepared in the background. Use it for search inputs filtering large lists.
useTransition: Keep Your UI Responsive During State Changes
useTransition lets you update state without blocking the UI, keeping your app responsive. Use it for slow renders like filtering large lists, while the `isPending` flag shows a loading state.
next/dynamic: Defer Loading Heavy Components
next/dynamic splits a component into its own file, loading it only when needed to shrink your initial bundle. Use it for heavy components below the fold or browser-only libraries. The footgun: forgetting a loading state causes layout shifts.
useLayoutEffect: Synchronous Effects Before Browser Paint
useLayoutEffect is useEffect's synchronous twin, running its code after DOM mutations but before the browser repaints. Use it to read DOM layout and re-render to prevent visual flickers, like positioning a tooltip. Its main footgun: it blocks rendering.
useMemo: Cache Expensive Calculations in React
The useMemo hook caches a function's return value, preventing slow calculations from running on every render. Use it to skip heavy data filtering unless its inputs change. The main footgun is a missing dependency, which leads to stale, cached data.
React's useCallback: Cache Functions, Not Just Values
useCallback gives you the same function instance across re-renders, as long as its dependencies are stable. This is key for optimizing child components with React.memo or preventing useEffect from re-running.
React Native's Bridgeless Mode
Bridgeless Mode replaces React Native's legacy message queue with direct calls between JavaScript and native code. This improves performance by removing the serialization bottleneck for UI rendering and native module calls.
React Native's Two Threads: JS and UI
React Native splits work between a JS thread for React logic and a UI thread for drawing pixels, keeping the app responsive. The JS thread runs your code and calculates layout, while the UI thread handles native view updates.
Reanimated Worklets: Run JS on the UI Thread
A Reanimated worklet is a JS function that runs directly on the UI thread, bypassing the bridge for 60fps animations. They're used in hooks like `useAnimatedStyle` to compute styles without dropping frames. The footgun: worklets capture their entire closure.
Turbo Modules: Type-Safe Native Code in React Native
Turbo Modules let your JS code call native APIs synchronously, skipping the slow async bridge. Use them to access device features or high-performance native libraries.
Profiling React Native on Android with System Tracing
System Tracing helps you find UI jank on Android by showing where time is spent in each 16ms frame. Use it in Android Studio to diagnose stuttering animations by inspecting the UI, JS, and Native Module threads.
Inline Requires: Defer JS Loading in React Native
Inline requires are just-in-time loading for code. Instead of loading everything at startup, you pull in modules only when needed, improving initial app speed. This is ideal for heavy components. The footgun: module side effects will execute later.
Why-Did-You-Render: Find Unnecessary React Re-renders
The `why-did-you-render` library is a detective for your React app, finding components that re-render unnecessarily. Use it in development to debug performance by spotting when new object or function references break memoization.
Analyzing Your React Native Bundle Size
Think of it as an X-ray for your app's final JavaScript file. It shows which libraries take up the most space, helping you shrink your app and improve startup time. The biggest mistake is only analyzing after performance degrades; do it proactively.
React's useMemo Hook: Cache Expensive Calculations
useMemo is React's cache for expensive calculations, preventing re-computation on every render. Use it for heavy tasks like filtering large lists. The main footgun is an incomplete dependency array, which leads to stale, cached data.
useCallback: Cache Functions Between Renders
useCallback caches a function so it's not recreated on every render. This is crucial for performance when passing callbacks as props to memoized components, preventing them from re-rendering unnecessarily.
Get Performance bites daily.
Five a day, five minutes, offline. With quizzes so it sticks.
Open testing — you’ll join as an early tester.