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.