Next.js Directives Cheat Sheet

Next.js Directives Cheatsheet

Client-Side Directives

'use client'

// Enable client-side features
'use client';

import { useState, useEffect } from 'react';

export default function ClientComponent() {
    const [count, setCount] = useState(0);
    
    useEffect(() => {
        console.log('Client-side effect');
    }, []);
    
    return (
        <button onClick={() => setCount(count + 1)}>
            Count: {count}
        </button>
    );
}

'use server'

// Server action in client component
'use client';

import { useFormState } from 'react-dom';

async function submitForm(prevState, formData) {
    'use server';
    
    const name = formData.get('name');
    await saveToDatabase(name);
    return { success: true };
}

export default function Form() {
    const [state, formAction] = useFormState(submitForm, {});
    
    return (
        <form action={formAction}>
            <input name="name" required />
            <button type="submit">Submit</button>
        </form>
    );
}

Rendering Directives

Dynamic Rendering

// Force dynamic rendering
export const dynamic = 'force-dynamic';

export default function DynamicPage() {
    return <div>Rendered on each request</div>;
}

// Auto dynamic rendering
export const dynamic = 'auto';

// Disable dynamic rendering
export const dynamic = 'error';

Static Rendering

// Force static rendering
export const dynamic = 'force-static';

export default function StaticPage() {
    return <div>Rendered at build time</div>;
}

Fetch Cache Control

// Force cache
export const fetchCache = 'force-cache';

// Disable cache
export const fetchCache = 'force-no-store';

// Auto cache
export const fetchCache = 'auto';

export default async function Page() {
    const data = await fetch('https://api.example.com/data');
    return <div>{/* content */}</div>;
}

Route Segment Config

Revalidation

// Revalidate every hour
export const revalidate = 3600;

// No revalidation
export const revalidate = false;

// Revalidate every 5 minutes
export const revalidate = 300;

export default function Page() {
    return <div>Content</div>;
}

Route Handlers

// app/api/users/route.js
export const dynamic = 'force-dynamic';
export const revalidate = 0;

export async function GET() {
    return Response.json({ users: [] });
}

export async function POST(request) {
    const data = await request.json();
    return Response.json({ success: true });
}

Metadata Directives

Metadata Configuration

// Static metadata
export const metadata = {
    title: 'My Page',
    description: 'Page description'
};

// Dynamic metadata
export async function generateMetadata({ params, searchParams }) {
    const data = await fetch(`/api/posts/${params.id}`);
    const post = await data.json();
    
    return {
        title: post.title,
        description: post.excerpt
    };
}

Viewport Configuration

export const viewport = {
    width: 'device-width',
    initialScale: 1,
    maximumScale: 1
};

Performance Directives

Bundle Optimization

// Optimize package imports
export const optimizePackageImports = ['lodash', 'react-icons'];

// Modularize imports
export const modularizeImports = {
    'react-icons': {
        transform: 'react-icons/{{member}}'
    }
};

Image Optimization

// app/components/Image.js
import Image from 'next/image';

export default function OptimizedImage({ src, alt }) {
    return (
        <Image
            src={src}
            alt={alt}
            width={500}
            height={300}
            priority={true} // Preload important images
            placeholder="blur"
            blurDataURL="data:image/jpeg;base64,..."
        />
    );
}

Conditional Directives

Environment-Based Configuration

// Conditional dynamic rendering
export const dynamic = process.env.NODE_ENV === 'production' 
    ? 'force-static' 
    : 'force-dynamic';

// Conditional revalidation
export const revalidate = process.env.NODE_ENV === 'development' 
    ? 0 
    : 3600;

Feature Flags

// Feature-based rendering
export const dynamic = process.env.ENABLE_DYNAMIC === 'true' 
    ? 'force-dynamic' 
    : 'force-static';

export default function FeaturePage() {
    return <div>Feature content</div>;
}

Error Handling Directives

Error Boundaries

// app/error.js
'use client';

export default function Error({ error, reset }) {
    return (
        <div>
            <h2>Something went wrong!</h2>
            <button onClick={reset}>Try again</button>
        </div>
    );
}

Not Found Pages

// app/not-found.js
export default function NotFound() {
    return (
        <div>
            <h2>Page not found</h2>
            <p>Could not find requested resource</p>
        </div>
    );
}

API Route Directives

API Route Configuration

// app/api/data/route.js
export const dynamic = 'force-dynamic';
export const revalidate = 0;

export async function GET() {
    const data = await fetch('https://api.example.com/data', {
        cache: 'no-store'
    });
    
    return Response.json(await data.json());
}

Middleware Configuration

// middleware.js
export const config = {
    matcher: [
        '/api/:path*',
        '/((?!_next/static|_next/image|favicon.ico).*)'
    ]
};

export function middleware(request) {
    // Middleware logic
}

Best Practices

Directive Placement

// ✅ Correct: Directives at the top
'use client';
import React from 'react';

export const dynamic = 'force-dynamic';
export const revalidate = 3600;

export default function Component() {
    return <div>Content</div>;
}

// ❌ Wrong: Directives after imports
import React from 'react';
'use client'; // This won't work

Performance Optimization

// Use static rendering by default
export const dynamic = 'force-static';

// Only use dynamic when necessary
export const dynamic = 'force-dynamic';

// Optimize revalidation times
export const revalidate = 3600; // 1 hour instead of 0

// Use appropriate cache strategies
export const fetchCache = 'force-cache'; // For static data
export const fetchCache = 'force-no-store'; // For dynamic data

Common Patterns

// Pattern 1: Server component with client interaction
// ServerComponent.js
export default function ServerComponent() {
    return (
        <div>
            <h1>Server rendered</h1>
            <ClientButton />
        </div>
    );
}

// ClientButton.js
'use client';
export default function ClientButton() {
    return <button onClick={() => alert('clicked')}>Click me</button>;
}

// Pattern 2: Conditional rendering
export const dynamic = process.env.NODE_ENV === 'development' 
    ? 'force-dynamic' 
    : 'force-static';

// Pattern 3: API route with caching
export const revalidate = 300; // 5 minutes
export const dynamic = 'force-dynamic';