PerformanceMedium

Techniques for improving website performance

01

The Short Answer

Website performance optimization spans three areas: reducing what you send (smaller bundles, fewer requests), speeding up delivery (caching, CDNs, compression), and optimizing what the browser does with it (efficient rendering, lazy loading, minimal DOM work). The goal is always the same — get meaningful content on screen as fast as possible and keep interactions responsive.

02

Reduce What You Send

The fastest request is the one you never make. The second fastest is the smallest one. These techniques reduce the total bytes and number of requests the browser needs to make.

Code splitting and lazy loading

Instead of shipping your entire application in one massive bundle, split it into chunks that load on demand. The user only downloads the code for the page they're viewing. In React, lazy() and Suspense make this straightforward — the component's code is fetched only when it's about to render.

code-splitting.tsxtypescript
import { lazy, Suspense } from 'react';

// This chunk only loads when the route is visited
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<Spinner />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

Tree shaking

Tree shaking eliminates dead code — functions and modules you import but never actually use. Modern bundlers (webpack, Rollup, esbuild) do this automatically with ES modules. The key is using named imports so the bundler can trace exactly what's used.

tree-shaking.tstypescript
// ✅ Tree-shakeable — bundler knows only 'debounce' is used
import { debounce } from 'lodash-es';

// ❌ Not tree-shakeable — imports the entire library
import _ from 'lodash';

Image optimization

Images are often the heaviest assets on a page. Use modern formats (WebP, AVIF), serve responsive sizes via srcset, and lazy-load images below the fold. Next.js <Image> handles all of this automatically.

03

Speed Up Delivery

Caching

Proper HTTP caching headers let the browser reuse previously downloaded resources without making a network request at all. Static assets with content hashes can be cached indefinitely, while dynamic content uses shorter TTLs or revalidation.

cache-headers.txttext
# Static assets with hash in filenamecache forever
Cache-Control: public, max-age=31536000, immutable

# HTML pagesalways revalidate
Cache-Control: no-cache

# API responsescache for 60 seconds, revalidate after
Cache-Control: public, max-age=60, stale-while-revalidate=300

CDN (Content Delivery Network)

A CDN serves your static assets from edge servers geographically close to the user. Instead of every request traveling to your origin server in one region, the CDN serves cached copies from the nearest point of presence. This dramatically reduces latency for users far from your server.

Compression

Gzip and Brotli compression reduce text-based assets (HTML, CSS, JS, JSON) by 60-80%. Brotli offers better compression ratios than Gzip and is supported by all modern browsers. Most hosting platforms enable this by default.

04

Optimize Browser Work

Minimize DOM manipulation

Every DOM change can trigger layout recalculation (reflow) and repaint. Batch your DOM updates, use documentFragment for bulk insertions, and avoid reading layout properties (like offsetHeight) between writes — this forces the browser to recalculate layout synchronously.

Virtualization for large lists

If you're rendering 10,000 rows, don't put 10,000 DOM nodes on the page. Virtualization (libraries like react-window or tanstack-virtual) only renders the items currently visible in the viewport — typically 20-50 nodes instead of thousands.

Debounce and throttle event handlers

Scroll, resize, and input events can fire hundreds of times per second. Throttle scroll handlers to run at most every 100ms, and debounce search inputs to wait until the user stops typing. This prevents unnecessary computation and network requests.

05

Loading Strategy

How and when you load resources has a massive impact on perceived performance. The techniques below control the priority and timing of resource loading to get critical content on screen first.

TechniqueWhat it doesUse for
preloadFetches resource early with high priorityCritical fonts, hero images, above-fold CSS
prefetchFetches resource at low priority for future navigationNext page's JS bundle, likely navigation targets
async (script)Downloads in parallel, executes immediately when readyAnalytics, third-party scripts that don't depend on DOM
defer (script)Downloads in parallel, executes after HTML parsingApp scripts that need the full DOM
loading="lazy"Defers image/iframe loading until near viewportBelow-fold images, embedded videos
06

Measuring Performance

You can't optimize what you don't measure. Core Web Vitals are Google's metrics for user experience, and they directly impact search rankings.

  • LCP (Largest Contentful Paint) — under 2.5s
    • How fast the main content appears
    • Optimize: preload hero image, inline critical CSS, fast server response
  • INP (Interaction to Next Paint) — under 200ms
    • How responsive the page feels to user input
    • Optimize: break long tasks, reduce JS execution time, use web workers
  • CLS (Cumulative Layout Shift) — under 0.1
    • How much the page jumps around during load
    • Optimize: set explicit dimensions on images/ads, avoid injecting content above existing content
07

Why Interviewers Ask This

Performance directly impacts user experience, conversion rates, and SEO. Interviewers ask this to gauge whether you think about performance proactively, know the common bottlenecks and their solutions, and can prioritize optimizations based on impact. They want to see a structured mental model — not just a random list of tricks, but an understanding of where time is spent and how to reduce it at each stage.

Quick Revision Cheat Sheet

Reduce payload: Code splitting, tree shaking, image optimization, compression

Speed delivery: CDN, HTTP caching, preload/prefetch critical resources

Optimize rendering: Virtualization, debounce/throttle, minimize reflows

Loading strategy: async/defer scripts, lazy load images, preload critical assets

Measure: Core Web Vitals — LCP < 2.5s, INP < 200ms, CLS < 0.1