Picovert

Frontend Performance Optimization Checklist 2026

2026-04-2810 min read

Performance is not one thing — it's the sum of dozens of small decisions. This checklist covers 30 items across six areas: images, fonts, JavaScript, CSS, caching, and rendering. Each item is ranked by typical impact. Tackle the top items first.

Images (highest impact)

  • Convert all images to WebP or AVIF. WebP cuts JPEG by 25–35% and PNG by 50–70%. Use Picovert's converter for static assets.
  • Never lazy-load the LCP image. Add fetchpriority="high" and a <link rel='preload'> in <head> instead.
  • Always specify width and height on every img. Prevents CLS from images loading without reserved space.
  • Use srcset with at least 3 sizes. 320w, 768w, 1200w covers mobile, tablet, and desktop. Cuts mobile payload by 50–60%.
  • Lazy-load below-the-fold images. loading="lazy" is now baseline in all modern browsers. Zero JavaScript needed.
  • Convert GIF animations to MP4. MP4 is 10–20x smaller and uses hardware decoding. Convert here.

Fonts

  • Use WOFF2 only. WOFF2 has 30% better compression than WOFF and is supported by 98% of browsers.
  • Subset fonts to characters you actually use. A full Latin font is 80 KB. Subset to your language's character set: 15–20 KB.
  • Preload critical fonts. <link rel="preload" as="font" crossorigin> removes the second-round-trip discovery delay.
  • Set font-display: swap on body fonts, optional on decorative fonts. Prevents invisible text during load (FOIT) while avoiding major layout shifts.
  • Self-host fonts instead of loading from Google Fonts. Eliminates a DNS lookup and connection to fonts.googleapis.com.

JavaScript

  • Split code at the route level. Each route should only load the JavaScript it needs. Next.js does this automatically for pages.
  • Audit and remove unused dependencies. Run npx bundle-phobia [package] before adding any new npm package.
  • Dynamic import heavy components. Rich text editors, chart libraries, PDF renderers — load them only when needed.
  • Replace moment.js with date-fns or dayjs.moment.js is 67 KB; date-fns is tree-shakeable to <5 KB for most use cases.
  • Defer all non-critical third-party scripts. Analytics, heatmaps, chatbots — load after the load event fires.
  • Enable React's production build. Development mode is 2–3x larger and slower. Verify with React DevTools profiler.

CSS

  • Inline critical CSS for above-the-fold content. The browser can render the visible portion without waiting for external stylesheets.
  • Remove unused CSS. Use PurgeCSS or Tailwind's JIT to ship only what your pages actually use.
  • Use contain: layout on isolated components. CSS containment prevents style recalculations from propagating across the tree.
  • Use will-change sparingly. Overuse promotes too many elements to compositor layers, consuming GPU memory.
  • Prefer CSS animations over JavaScript animations. CSS animations run on the compositor thread and don't block the main thread.

Caching

  • Set long-lived cache headers on static assets. Cache-Control: max-age=31536000, immutable for hashed filenames (JS, CSS, images). Immutable tells the browser not to revalidate.
  • Enable stale-while-revalidate for HTML. Serves the cached HTML immediately while fetching the update in the background.
  • Deploy to a CDN with edge nodes close to users.Reduces round-trip latency from 150 ms to <10 ms for most global traffic.
  • Configure ETag or Last-Modified on dynamic assets. Allows 304 Not Modified responses, saving bandwidth on unchanged resources.

Rendering

  • Use Next.js App Router RSC for data-heavy pages. Server Components stream HTML without shipping their own JavaScript to the client.
  • Streaming HTML with Suspense boundaries. Users see content progressively instead of waiting for the slowest data dependency.
  • Minimize hydration scope. Only hydrate the interactive parts of a page. Static content should stay server-rendered.
  • Use content-visibility: auto on off-screen sections. The browser skips layout and paint for invisible content, cutting rendering time by 40–60% on long pages.
  • Measure, don't guess. Run Lighthouse, check CrUX data in Search Console, and use the web-vitals library with your own RUM data before and after each change.

Priority matrix

AreaMax LCP gainMax INP gainMax CLS gain
ImagesHighLowHigh (size attributes)
FontsMediumLowHigh (font-display)
JavaScriptMediumHighLow
CSSMediumMediumLow
CachingHigh (repeat visits)LowLow
RenderingHigh (streaming)High (hydration)Low