Zum Inhalt springen

Next.js

# Using create-next-app (recommended)
npx create-next-app@latest my-app
cd my-app

# With TypeScript
npx create-next-app@latest my-app --typescript

# With tailwind CSS
npx create-next-app@latest my-app --tailwind

# Manual setup
npm init -y
npm install react react-dom next
my-app/
├── app/                    # App router (Next.js 13+)
│   ├── page.js            # Root route
│   ├── layout.js          # Root layout
│   └── api/               # API routes
├── pages/                 # Pages router (older)
├── public/                # Static files
├── styles/                # CSS/SCSS
├── components/            # React components
├── lib/                   # Utility functions
├── next.config.js         # Next.js config
├── package.json
└── tsconfig.json
BefehlBeschreibung
npm run devDev-Server starten (localhost:3000)
npm run buildFür Produktion erstellen
npm run startProduktions-Server starten
npm run lintESLint ausführen
npm testTests ausführen (falls konfiguriert)
# app/page.js - Home page (/)
export default function Home() {
  return <h1>Home Page</h1>
}

# app/about/page.js - About page (/about)
export default function About() {
  return <h1>About Page</h1>
}

# app/blog/[id]/page.js - Dynamic route (/blog/1, /blog/2, etc)
export default function BlogPost({ params }) {
  return <h1>Blog Post: {params.id}</h1>
}

# app/docs/[[...slug]]/page.js - Catch-all route (/docs/a/b/c)
export default function Docs({ params }) {
  return <pre>{JSON.stringify(params, null, 2)}</pre>
}
// app/layout.js - Root layout
export const metadata = {
  title: 'My App',
  description: 'Generated by create next app',
}

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

// app/dashboard/layout.js - Dashboard layout
export default function DashboardLayout({ children }) {
  return (
    <div>
      <nav>Dashboard Navigation</nav>
      <main>{children}</main>
    </div>
  )
}
// app/api/hello/route.js
export async function GET(request) {
  return Response.json({ message: 'Hello World' })
}

// app/api/users/route.js
export async function GET() {
  const users = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' },
  ]
  return Response.json(users)
}

export async function POST(request) {
  const data = await request.json()
  // Process POST data
  return Response.json({ created: true, data })
}

// app/api/users/[id]/route.js - Dynamic API route
export async function GET(request, { params }) {
  const userId = params.id
  // Fetch user by ID
  return Response.json({ id: userId, name: 'User' })
}

export async function PUT(request, { params }) {
  const data = await request.json()
  // Update user
  return Response.json({ updated: true, ...data })
}

export async function DELETE(request, { params }) {
  const userId = params.id
  // Delete user
  return Response.json({ deleted: true, id: userId })
}
// app/api/search/route.js
export async function GET(request) {
  const searchParams = request.nextUrl.searchParams
  const query = searchParams.get('q')
  const limit = searchParams.get('limit') || '10'

  // /api/search?q=next.js&limit=20
  return Response.json({
    query,
    limit,
    results: []
  })
}
// app/blog/page.js - Server component by default
async function getBlogPosts() {
  const res = await fetch('https://api.example.com/posts')
  return res.json()
}

export default async function Blog() {
  const posts = await getBlogPosts()

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
// Caching für bestimmte Routen deaktivieren
export const revalidate = 0 // No caching
export const revalidate = 60 // Cache for 60 seconds (ISR)

export default async function Page() {
  const data = await fetch('https://api.example.com/data')
  return <div>{/* content */}</div>
}
// app/posts/page.js - Revalidate every hour
export const revalidate = 3600

export default function Posts({ posts }) {
  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}
// app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

export const revalidate = 3600 // Revalidate every hour

export default function BlogPost({ params }) {
  return <h1>Post: {params.slug}</h1>
}
'use client'

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>
  )
}
'use client'

import { useEffect, useState } from 'react'

export default function UserList() {
  const [users, setUsers] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchUsers = async () => {
      const res = await fetch('/api/users')
      const data = await res.json()
      setUsers(data)
      setLoading(false)
    }

    fetchUsers()
  }, [])

  if (loading) return <p>Loading...</p>

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}
import Image from 'next/image'

export default function MyImage() {
  return (
    <Image
      src="/profile.jpg"
      alt="Profile picture"
      width={200}
      height={200}
      priority  // Load immediately
    />
  )
}

// With external image
export default function ExternalImage() {
  return (
    <Image
      src="https://example.com/image.jpg"
      alt="External image"
      width={300}
      height={300}
    />
  )
}
// app/page.js
export const metadata = {
  title: 'Home Page',
  description: 'Welcome to my website',
  keywords: 'next.js, react, web development',
  openGraph: {
    title: 'My Website',
    description: 'Welcome',
    url: 'https://mywebsite.com',
    images: [
      {
        url: 'https://mywebsite.com/og.jpg',
        width: 1200,
        height: 630,
      },
    ],
  },
}

export default function Page() {
  return <h1>Home</h1>
}
// app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug)

  return {
    title: post.title,
    description: post.excerpt,
  }
}

export default function BlogPost({ params }) {
  return <h1>{post.title}</h1>
}
# .env.local
DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY=secret_key_123
NEXT_PUBLIC_API_URL=https://api.example.com

# .env.production
DATABASE_URL=postgresql://prod-user:pass@prod-db/db
// Server-side (any file)
const dbUrl = process.env.DATABASE_URL
const apiKey = process.env.API_KEY

// Client-side (must start with NEXT_PUBLIC_)
const apiUrl = process.env.NEXT_PUBLIC_API_URL

// In client components
'use client'
export default function Component() {
  const apiUrl = process.env.NEXT_PUBLIC_API_URL
  return <div>{apiUrl}</div>
}
// middleware.js (root directory)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // Check authentication
  const token = request.cookies.get('token')?.value

  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

// Specify which routes use middleware
export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
}
// app/api/login/route.js
export async function POST(request) {
  const { email, password } = await request.json()

  // Verify credentials
  if (email === 'user@example.com' && password === 'password') {
    // Create token/session
    const response = Response.json({ success: true })
    response.cookies.set('token', 'jwt-token-here', {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'strict',
    })
    return response
  }

  return Response.json({ error: 'Invalid credentials' }, { status: 401 })
}

// app/api/logout/route.js
export async function POST() {
  const response = Response.json({ success: true })
  response.cookies.delete('token')
  return response
}
# Install Prisma
npm install @prisma/client
npm install -D prisma

# Initialize Prisma
npx prisma init

# Generate Prisma client after updating schema
npx prisma generate
npx prisma migrate dev --name init
// lib/db.js
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()
export default prisma

// app/api/users/route.js
import prisma from '@/lib/db'

export async function GET() {
  const users = await prisma.user.findMany()
  return Response.json(users)
}

export async function POST(request) {
  const data = await request.json()
  const user = await prisma.user.create({ data })
  return Response.json(user)
}
# Install Vercel CLI
npm i -g vercel

# Deploy
vercel

# Deploy to production
vercel --prod

# Environment variables
vercel env add DATABASE_URL
# Build for production
npm run build

# Start production server
npm run start

# Or with PM2
pm2 start npm --name "nextjs" -- start
pm2 save
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
import dynamic from 'next/dynamic'

const HeavyComponent = dynamic(() => import('@/components/Heavy'), {
  loading: () => <p>Loading...</p>,
})

export default function Page() {
  return <HeavyComponent />
}
import { Inter, Roboto } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })
const roboto = Roboto({ weight: '400' })

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}
  • Standardmäßig Server-Komponenten verwenden für bessere Leistung
  • Richtige Error Boundaries implementieren
  • Dynamische Imports für Code-Splitting verwenden
  • Bilder mit Next.js Image-Komponente optimieren
  • Richtige Caching-Strategien einrichten (ISR, revalidate)
  • Umgebungsvariablen für sensible Daten verwenden
  • Richtige Fehlerbehandlung in API-Routen implementieren
  • Core Web Vitals und Leistungsmetriken überwachen

Last updated: 2026-03-30