Why Performance Is a Feature
Every 100ms of latency costs Amazon approximately 1% of revenue — a statistic from 2007 that has only become more relevant. Google's research shows that as page load time increases from 1 second to 3 seconds, bounce rate increases 32%. From 1 to 6 seconds, it increases 106%.
Performance also directly affects search ranking. Google's Core Web Vitals are ranking signals — a slow page is penalized in search results compared to a fast competitor with similar content. Speed is SEO.
This checklist covers the highest-impact optimizations across the full stack.
Images: The Biggest Win
Images typically account for 50–75% of page weight. This is where most performance gains come from.
- Use modern formats: WebP is 25–35% smaller than JPEG/PNG at equivalent quality. AVIF is 50% smaller than JPEG. Both are supported by all modern browsers. Serve WebP with a JPEG/PNG fallback using the
<picture>element. - Set explicit dimensions: Always set
widthandheighton<img>elements. This prevents Cumulative Layout Shift (CLS) — the jarring jump when images load and push content down. - Lazy load below-fold images:
<img loading="lazy">defers loading until the image is near the viewport. Free performance with a one-word attribute change. - Use
srcsetfor responsive images: Serve different image sizes for different viewport widths. A mobile user should not download a 2000px-wide image. - Preload the LCP image: The Largest Contentful Paint (LCP) element — usually your hero image — should be preloaded:
<link rel="preload" as="image" href="hero.webp">
JavaScript Bundle Optimization
Code splitting — Load only the JavaScript needed for the current route. In React, use React.lazy() with Suspense to split at the route level. Users visiting your homepage should not download code for your dashboard.
Tree shaking — Modern bundlers (Vite, Rollup, Webpack) eliminate unused exports automatically when using ES modules. Avoid importing entire libraries when you only need a few functions:
// Bad — imports entire lodash bundle
import _ from 'lodash';
const result = _.debounce(fn, 300);
// Good — only imports the debounce function
import debounce from 'lodash/debounce';
const result = debounce(fn, 300);
Minification — Always minify JavaScript for production. Use esbuild (fast) or Terser (more aggressive). Use PureFormatter's JS Minifier for one-off tasks.
Bundle analysis — Use vite-plugin-visualizer or webpack-bundle-analyzer to see exactly what is in your bundle. Dependencies that are surprisingly large (moment.js, lodash, chart.js) are often candidates for replacement or targeted imports.
CSS Performance
CSS blocks rendering — the browser cannot display content until all CSS in the <head> has been parsed. Keep your CSS lean:
- Remove unused CSS with PurgeCSS (integrates with Vite, Webpack, PostCSS)
- Avoid large framework payloads when you use 5% of their classes — consider Tailwind CSS which removes unused utilities automatically
- Minify your stylesheets for production using PureFormatter's CSS Minifier
- Inline critical CSS (above-the-fold styles) in a
<style>tag to unblock initial rendering
Fonts
Custom fonts are a common performance culprit. Best practices:
- Use
font-display: swapto show text in a fallback font while the custom font loads — prevents invisible text during loading - Preload your primary font file:
<link rel="preload" as="font" type="font/woff2" href="/fonts/main.woff2" crossorigin> - Subset your fonts to include only the characters you need (Latin-only, removing Cyrillic/Greek if not needed, can save 60%+ of font file size)
- Prefer variable fonts — one file covers multiple weights and styles instead of loading separate files for each
Caching Strategy
Effective caching means returning users load your site almost instantly from their browser cache.
- Cache static assets aggressively: Set
Cache-Control: public, max-age=31536000, immutablefor hashed assets (JS, CSS bundles with content hashes in their filenames) - Cache HTML conservatively: HTML references your JS/CSS assets, so it should have a short cache time (
no-cacheormax-age=0) so updates propagate quickly - Use a CDN: Serve static assets from a CDN edge network close to your users. CDNs dramatically reduce latency for globally distributed audiences.
Core Web Vitals: Your Performance Report Card
Google measures page experience using Core Web Vitals. These are the targets you need to hit for optimal ranking and user experience:
- LCP (Largest Contentful Paint) — under 2.5 seconds. Optimize your hero image and server response time.
- INP (Interaction to Next Paint) — under 200ms. Optimize JavaScript execution and avoid blocking the main thread.
- CLS (Cumulative Layout Shift) — under 0.1. Set dimensions on images, avoid inserting content above existing content.
Measure your scores with Lighthouse (built into Chrome DevTools), PageSpeed Insights, or web.dev/measure. Run measurements on mobile as well as desktop — mobile scores are typically 2–3x worse and represent the majority of your traffic.
Server-Side Wins
Performance is not just about the browser. Server response time (Time to First Byte, TTFB) directly impacts all other metrics:
- Enable Brotli compression on your server (30–40% better than gzip)
- Use HTTP/2 or HTTP/3 for multiplexed request handling
- Cache expensive database queries with Redis or an in-memory cache
- Use connection pooling for your database
- Consider edge computing (Cloudflare Workers, Vercel Edge Functions) for globally fast responses