#nextjs #performance #core-web-vitals #script

Day 27 — Performance Optimization: Core Web Vitals

🧭 Day 27 — Performance Optimization: Core Web Vitals

Zero to Hero — Hands-on Next.js Tutorial

We’ve built a lot. Now let’s make it fast. Google ranks sites based on Core Web Vitals:

  1. LCP (Largest Contentful Paint): Loading speed.
  2. FID/INP (Interaction to Next Paint): Responsiveness.
  3. CLS (Cumulative Layout Shift): Visual stability.

🟦 1. The <Script> Component

Third-party scripts (Google Analytics, Chat Widgets, Ads) are the enemy of performance. If you put <script src="..."> in your head, it blocks the page load.

Next.js provides next/script.

import Script from 'next/script'
 
export default function Page() {
  return (
    <>
      <Script 
        src="https://example.com/analytics.js" 
        strategy="lazyOnload" 
      />
    </>
  )
}

Strategies:

  • beforeInteractive: Load before hydration (rare, e.g., bot detection).
  • afterInteractive (Default): Load immediately after hydration (e.g., Analytics).
  • lazyOnload: Load later during idle time (e.g., Chat widgets). Use this mostly!

🟩 2. Bundle Analysis

How big is your JavaScript? Install the bundle analyzer:

npm install @next/bundle-analyzer

Run it to see a visual map of your modules. If you see a huge library (like lodash or moment.js), replace it with a smaller alternative (like date-fns).


🟧 3. Lazy Loading Components

If you have a Heavy Component (e.g., a massive Chart or 3D Model) that is below the fold, don’t load it initially.

import dynamic from 'next/dynamic'
 
const HeavyChart = dynamic(() => import('../components/HeavyChart'), {
  loading: () => <p>Loading...</p>,
  ssr: false, // Disable SSR if it relies on window
})

export default function Page() {
  return <HeavyChart />
}

🟥 4. Image Optimization Recap

Remember Day 6!

  • Use priority on your Hero Image (LCP).
  • Use specific width/height to prevent CLS.

🧪 Challenge: Day 27

  1. Add a dummy script (e.g., a console log file) using lazyOnload.
  2. Import a component using dynamic().
  3. Run the production build (npm run build).
  4. Look at the “First Load JS” sizes in the terminal.
  5. Try to keep the generic pages under 100kB!

See you tomorrow for Testing (Unit & E2E)! 🧪