Skip to content

๐Ÿš€ Performance - Beyond the Bundle

The fastest JavaScript is the JavaScript that never gets sent to the browser. A Programmer views every kilobyte of JS as a โ€œperformance debtโ€ that costs the user CPU cycles, battery life, and data.


Modern apps are often bloated by third-party libraries and large component trees.

  • Tree Shaking: A build-step optimization (Webpack/Rollup/Vite) that removes โ€œdead codeโ€ (imported functions that arenโ€™t actually used).
    • Tip: Use ES Modules (import/export) instead of CommonJS (require) to ensure the bundler can statically analyze and prune your code.
  • Route-Based Splitting: Only load the code needed for the current page. If a user is on the /login page, they shouldnโ€™t download the code for the /dashboard.
  • Vendor Splitting: Separate your frequently changing application code from rarely changing libraries (React, Lodash). This allows the browser to cache the vendor.js file indefinitely.

Donโ€™t let non-essential assets block the initial render.

  • Component Lazy Loading: Use React.lazy or dynamic import() to load heavy components (like a Data Grid or a Map) only when they are needed.
  • Images & Iframes: Use the native loading="lazy" attribute.
  • Priority Hints: Use <link rel="preload"> for critical assets (like your main LCP image or branding font) and fetchpriority="high" to tell the browser what to grab first.

Hydration is the process where a static HTML page (from SSR) becomes an interactive app. It is often the โ€œQuiet Killerโ€ of performance.

  • The Problem: The browser has to download the JS, parse it, and โ€œattachโ€ event listeners to the existing HTML. During this time, the page looks ready but is unresponsive (high Total Blocking Time).
  • Progressive Hydration: Only hydrating parts of the page as they enter the viewport.
  • Selective Hydration: Prioritizing the hydration of components the user is currently interacting with.
  • Resumability (Qwik): A new paradigm where the serialized state is sent in the HTML, allowing the app to โ€œresumeโ€ without a full hydration step.

MetricWhat it measuresOptimization Goal
LCP (Largest Contentful Paint)Perceived load speed.Optimize images; use preconnect/preload; minimize render-blocking CSS.
INP (Interaction to Next Paint)Responsiveness to user input.Break up long tasks; use requestIdleCallback; optimize state updates.
CLS (Cumulative Layout Shift)Visual stability.Set explicit dimensions for images/ads; avoid inserting content above existing content.

Set a โ€œPerformance Budget.โ€ If a PR increases the bundle size beyond a certain threshold, it requires a justification.

  • Strategy: Use tools like BundleStats or Lighthouse CI in your CI/CD pipeline to catch โ€œbundle bloatโ€ before it hits production.

Donโ€™t wait for the user to click.

  • Speculative Prefetching: If a user hovers over a link, start prefetching the data/code for that page. (Next.js does this automatically for links in the viewport).

JS is single-threaded. If you have to do heavy data processing (e.g., parsing a 5MB JSON), move it to a Web Worker. This keeps the main thread free to handle user input and animations.

Stop using .png or .jpg for everything.

  • AVIF/WebP: These formats offer 30-50% better compression.
  • Responsive Images: Use <picture> and srcset to serve a 400px image to a mobile phone and a 2000px image to a 4K monitor.

๐Ÿ’ก Note: โ€œFlashyโ€ animations and high-res videos are great for marketing, but they are the enemy of performance. Always advocate for a โ€œPerformance-Firstโ€ design where the Time to Interactive is more important than the โ€œwow factor.โ€