What are Components in Next.js?

Next.js components are React components with additional features for optimization, routing, and data fetching.

Next.js enhances React components with: Server Components, automatic code splitting, built-in optimization for images/fonts, and more.

Component Categories

Server Components

Default in Next.js App Router

  • Render on the server
  • Zero JavaScript to client
  • Can access backend resources
  • Improved performance
Client Components

Use 'use client' directive

  • Interactive features
  • Use React hooks
  • Browser APIs access
  • Event listeners

Server vs Client Components

Server Component (Default)

// app/components/UserProfile.tsx
// This is a Server Component by default

async function UserProfile({ userId }: { userId: string }) {
  // Can directly fetch data on server
  const user = await fetch(`https://api.example.com/users/${userId}`)
    .then(res => res.json())

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  )
}

export default UserProfile

Client Component

'use client' // This directive makes it a Client Component

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  )
}

When to Use Each

Use Case Server Component Client Component
Fetch data ✅ ❌
Access backend resources ✅ ❌
Use React hooks (useState, useEffect) ❌ ✅
Event listeners (onClick, onChange) ❌ ✅
Browser APIs (localStorage, etc.) ❌ ✅
Keep sensitive data on server ✅ ❌
Best Practice: Use Server Components by default, and only use Client Components when you need interactivity.

Next.js Image Component

The Image component extends the HTML <img> element with automatic optimization.

Basic Usage

import Image from 'next/image'

export default function Avatar() {
  return (
    <Image
      src="/profile.jpg"
      alt="Profile picture"
      width={500}
      height={500}
    />
  )
}

Remote Images

import Image from 'next/image'

export default function RemoteImage() {
  return (
    <Image
      src="https://example.com/photo.jpg"
      alt="Remote photo"
      width={800}
      height={600}
      priority // Load image with high priority
    />
  )
}

// next.config.js - Configure remote domains
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
      },
    ],
  },
}

Fill Container

import Image from 'next/image'

export default function BackgroundImage() {
  return (
    <div style={{ position: 'relative', width: '100%', height: '400px' }}>
      <Image
        src="/background.jpg"
        alt="Background"
        fill
        style={{ objectFit: 'cover' }}
      />
    </div>
  )
}

Key Features

  • Automatic Optimization: Serves modern formats (WebP, AVIF)
  • Responsive: Automatically generates multiple sizes
  • Lazy Loading: Images load as they enter viewport
  • Blur Placeholder: Show blur-up preview while loading
  • Priority Loading: Preload critical images (LCP)
Important: Always provide width and height (or use fill) to prevent layout shift.

Next.js Script Component

The Script component optimizes loading of third-party scripts.

Loading Strategies

import Script from 'next/script'

export default function Page() {
  return (
    <>
      {/* Load after page is interactive (default) */}
      <Script
        src="https://example.com/script.js"
        strategy="afterInteractive"
      />

      {/* Load before page is interactive */}
      <Script
        src="https://example.com/critical.js"
        strategy="beforeInteractive"
      />

      {/* Load during browser idle time */}
      <Script
        src="https://example.com/analytics.js"
        strategy="lazyOnload"
      />
    </>
  )
}

Inline Scripts

import Script from 'next/script'

export default function Page() {
  return (
    <Script id="show-banner" strategy="lazyOnload">
      {`
        console.log('Page loaded!')
        document.getElementById('banner').style.display = 'block'
      `}
    </Script>
  )
}

Event Handlers

import Script from 'next/script'

export default function Page() {
  return (
    <Script
      src="https://example.com/script.js"
      onLoad={() => {
        console.log('Script loaded successfully')
      }}
      onError={(e) => {
        console.error('Script failed to load', e)
      }}
    />
  )
}

Font Optimization

Next.js automatically optimizes fonts to eliminate layout shift.

Google Fonts

// app/layout.tsx
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

const robotoMono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

Local Fonts

import localFont from 'next/font/local'

const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}

Multiple Weights

import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: ['400', '700'],
  style: ['normal', 'italic'],
  subsets: ['latin'],
  display: 'swap',
})
Benefits: Fonts are self-hosted, zero layout shift, and no external network requests.