Comprehensive Performance Checklist
Use this checklist for auditing existing sites or ensuring new projects launch with optimal performance. Check items as you implement them.
A. Strategy & Measurement
Performance Culture
- [ ] Performance goals are documented and shared with the full team
- [ ] Representative test device chosen (mid-range Android, e.g. Samsung Galaxy A15)
- [ ] Competitive performance benchmarking completed (target: 20% faster than fastest competitor)
- [ ] Performance champion or rotating role assigned
- [ ] Performance metrics included in sprint reviews and team dashboards
Core Web Vitals Targets
- [ ] LCP β€ 2.5s at P75 (field data)
- [ ] INP β€ 200ms at P75 (field data)
- [ ] CLS β€ 0.1 at P75 (field data)
- [ ] TTFB β€ 800ms at P75
- [ ] FCP β€ 1.8s at P75
Performance Budgets & Monitoring
- [ ] JavaScript budget set (<200KB gzipped total)
- [ ] CSS budget set (<50KB gzipped)
- [ ] Image budget per page defined
- [ ] Performance budgets enforced in CI/CD (Size-limit, Lighthouse CI, Bundlewatch)
- [ ] Real User Monitoring (RUM) collecting Core Web Vitals in production
- [ ] CrUX data monitored in Google Search Console
- [ ] Synthetic monitoring (Lighthouse/WebPageTest) running on key pages on schedule
- [ ] Alerting configured for metric regressions
B. JavaScript & Build Pipeline
Build Tools
- [ ] Using a modern bundler (Vite 8, Rspack, Turbopack, or equivalent)
- [ ] Linting with Oxlint or Biome (50β100Γ faster than ESLint)
- [ ] TypeScript type-checking optimized (tsgo or incremental builds)
- [ ] Production builds use minification and compression
Code Splitting & Tree Shaking
- [ ] Route-based code splitting implemented
- [ ] Heavy components lazy-loaded with
React.lazy()or dynamicimport() - [ ] Barrel files eliminated or optimized (barrel-begone, direct imports)
- [ ]
sideEffects: falseconfigured inpackage.jsonwhere safe - [ ] Dead code detection run (Knip) and unused exports removed
- [ ] Bundle analyzer run to identify largest dependencies
JavaScript Execution
- [ ] No synchronous third-party scripts in
<head> - [ ] Long tasks broken up with
scheduler.yield()orscheduler.postTask() - [ ] Heavy computation offloaded to Web Workers where appropriate
- [ ] Speculation Rules or
prefetchconfigured for likely next navigations - [ ]
deferortype="module"used on all non-critical scripts
C. Rendering & Frameworks
Rendering Strategy
- [ ] Appropriate rendering strategy chosen (SSR/SSG/ISR/Streaming/Islands) for the content type
- [ ] Server-side rendering used for content-heavy pages
- [ ] Static generation used for pages that change infrequently
- [ ] Streaming SSR with Suspense boundaries for progressive loading
React Optimization (if applicable)
- [ ] React Server Components used for non-interactive content
- [ ] React Compiler enabled (eliminates manual memoization)
- [ ]
startTransitionused for non-urgent state updates - [ ] Virtual lists used for long scrollable lists (TanStack Virtual)
- [ ] Context providers split to minimize re-render blast radius
- [ ] State management library chosen appropriately (Zustand/Jotai for most cases)
- [ ] TanStack Query or SWR used for server state (caching, deduplication)
D. Assets & Loading
Images
- [ ] AVIF served as primary format with WebP and JPEG fallbacks via
<picture> - [ ] Responsive images implemented with
srcsetandsizes - [ ] LCP image has
fetchpriority="high"and is NOT lazy-loaded - [ ] Below-fold images have
loading="lazy"anddecoding="async" - [ ] All
<img>elements have explicitwidthandheightattributes - [ ] LCP image preloaded in
<head>(especially if CSS background-image or deep in DOM) - [ ] Images compressed with Squoosh, Sharp, or an image CDN
- [ ] SVGs optimized with SVGO/SVGOMG
- [ ] Animated GIFs replaced with
<video autoplay loop muted playsinline>(AV1/H.264)
CSS
- [ ] Critical CSS inlined in
<head>(<14KB compressed) - [ ] Remaining CSS loaded asynchronously
- [ ]
content-visibility: autoapplied to off-screen content sections - [ ] CSS
@layerused for specificity management - [ ] Unused CSS removed (PurgeCSS, Coverage tab, or framework tree-shaking)
- [ ] CSS Modules, vanilla-extract, or Tailwind used (zero-runtime)
- [ ] No runtime CSS-in-JS (styled-components/Emotion) in new projects
- [ ] Native CSS nesting used instead of Sass where possible
Modern CSS Replacing JavaScript
- [ ] Container queries used instead of JS-based
ResizeObserverfor component responsiveness - [ ]
:has()used for parent/sibling-based conditional styling instead of JS state - [ ] Scroll-driven animations used instead of GSAP/ScrollMagic where possible (with
prefers-reduced-motion) - [ ] CSS anchor positioning evaluated for tooltips/popovers (replacing Floating UI)
- [ ] Popover API used for show/hide overlays (replacing custom JS modal logic)
- [ ] View Transitions API evaluated for page/state transitions
- [ ]
interpolate-size: allow-keywordsadded to CSS reset - [ ]
@starting-styleused for entry/exit animations fromdisplay: none
Fonts
- [ ] WOFF2 format used exclusively (no TTF/OTF/EOT/SVG)
- [ ] Fonts self-hosted (not loaded from Google Fonts CDN)
- [ ]
font-display: swaporoptionalset on all@font-facerules - [ ] Font metric overrides configured (
size-adjust,ascent-override,descent-override) to minimize CLS - [ ] Fonts subsetted to required character ranges with
unicode-range - [ ] Only necessary weights loaded (2β3 max; consider variable fonts for 3+)
- [ ] Critical font preloaded with
<link rel="preload" as="font" crossorigin> - [ ] Icon fonts replaced with SVG icons (Lucide, Heroicons, or inline SVG)
- [ ] Font files cached with long
max-age+immutable
Third-Party Scripts
- [ ] All third-party scripts load with
asyncordefer(none synchronous) - [ ] Facade pattern used for heavy embeds (YouTube, chat widgets, maps)
- [ ] Third-party scripts loaded after user interaction or after page load where possible
- [ ] Partytown evaluated for offloading remaining heavy third-party scripts to Web Workers
- [ ] Consent mode configured (donβt load tracking before consent where legally required)
- [ ] Tag manager audited quarterly; unused tags removed
- [ ] Third-party JavaScript budget set and enforced (<100KB compressed)
- [ ] Content Security Policy (CSP) configured to restrict script sources
Resource Hints
- [ ]
<link rel="preconnect">added for 2β4 critical third-party origins - [ ]
<link rel="dns-prefetch">added for non-critical third-party domains - [ ] LCP image preloaded (with
imagesrcset/imagesizesfor responsive) - [ ] Critical font preloaded
- [ ]
modulepreloadused for critical JS entry point modules - [ ]
fetchpriority="high"on LCP element;fetchpriority="low"on non-critical images - [ ] Speculation Rules configured for likely next navigations
- [ ] 103 Early Hints enabled at CDN level (if supported)
- [ ] No over-preloading (limit to 1β3 truly critical resources)
E. Infrastructure & Networking
Network Protocols & Compression
- [ ] HTTPS enforced with HSTS (consider HSTS preload)
- [ ] TLS 1.3 enabled; TLS 1.0/1.1 disabled
- [ ] HTTP/2 enabled (minimum)
- [ ] HTTP/3 (QUIC) enabled at CDN or server level
- [ ] Brotli compression enabled for text assets (CSS, JS, HTML, SVG, JSON)
- [ ] Zstandard (zstd) compression evaluated for dynamic content
- [ ] Images, WOFF2 fonts, and video NOT double-compressed via HTTP compression
- [ ] TCP BBR congestion control enabled on Linux servers
CDN & Caching
- [ ] CDN in use for all static assets
- [ ] Fingerprinted assets cached with
max-age=31536000, immutable - [ ] HTML/API responses use
stale-while-revalidatefor speed + freshness - [ ]
Vary: Accept-Encodingset on compressed responses - [ ]
s-maxageused for CDN-specific cache TTLs where appropriate - [ ] Edge functions used for latency-sensitive dynamic logic (auth, geo, A/B)
- [ ] Service worker caching strategy implemented (Cache First for static, SWR for dynamic)
- [ ] No caching of personalized/authenticated content in shared caches (
private)
F. Quality, Security & DX
Testing & Debugging
- [ ] Lighthouse CI configured in deployment pipeline with assertion thresholds
- [ ] Bundle size budgets enforced in CI (Size-limit or Bundlewatch)
- [ ] Performance regression = blocking PR check (not advisory)
- [ ] WebPageTest used for deep waterfall analysis of key pages
- [ ] Chrome DevTools Performance panel used for INP/LCP debugging
- [ ] Coverage tab checked for unused CSS/JS
Security
- [ ] HTTPS with HSTS and preload list submission
- [ ] Content Security Policy deployed (even if Report-Only initially)
- [ ] Subresource Integrity (SRI) on CDN-hosted scripts
- [ ] Permissions Policy configured (disable unused features for iframes)
- [ ] Dependencies audited (
npm audit, Socket.dev) - [ ] No third-party polyfill CDNs (self-host or use Cloudflare alternative)
Accessibility + Performance
- [ ]
prefers-reduced-motionrespected (all animations wrapped in media query) - [ ]
prefers-reduced-transparencyrespected where applicable - [ ] Semantic HTML used (reducing need for JS-powered interactivity)
- [ ] Popover API and
<dialog>used instead of custom JS modals - [ ] Keyboard navigation works without JavaScript where possible
Developer Experience
- [ ] Fast HMR/Fast Refresh configured (<100ms feedback loop)
- [ ] Monorepo tooling (Turborepo/Nx) with remote caching if applicable
- [ ] Performance tested on a real mid-range Android device, not just desktop
- [ ] Team educated on performance impact of
npm installdecisions