Next.js
Installation und Einrichtung
Abschnitt betitelt „Installation und Einrichtung“Neues Projekt erstellen
Abschnitt betitelt „Neues Projekt erstellen“# 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
Projektstruktur
Abschnitt betitelt „Projektstruktur“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
Entwicklungsbefehle
Abschnitt betitelt „Entwicklungsbefehle“| Befehl | Beschreibung |
|---|---|
npm run dev | Dev-Server starten (localhost:3000) |
npm run build | Für Produktion erstellen |
npm run start | Produktions-Server starten |
npm run lint | ESLint ausführen |
npm test | Tests ausführen (falls konfiguriert) |
Seiten und Routing (App Router)
Abschnitt betitelt „Seiten und Routing (App Router)“Grundlegende Routen
Abschnitt betitelt „Grundlegende Routen“# 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>
}
Layout-Komponenten
Abschnitt betitelt „Layout-Komponenten“// 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>
)
}
API-Routen
Abschnitt betitelt „API-Routen“API-Endpunkte erstellen
Abschnitt betitelt „API-Endpunkte erstellen“// 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 })
}
Abfrageparameter handhaben
Abschnitt betitelt „Abfrageparameter handhaben“// 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: []
})
}
Serverseitiges Rendering (SSR)
Abschnitt betitelt „Serverseitiges Rendering (SSR)“Server-Komponenten
Abschnitt betitelt „Server-Komponenten“// 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>
)
}
Dynamisches serverseitiges Rendering
Abschnitt betitelt „Dynamisches serverseitiges Rendering“// 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>
}
Statische Site-Generierung (SSG)
Abschnitt betitelt „Statische Site-Generierung (SSG)“Statische Generierung mit revalidate
Abschnitt betitelt „Statische Generierung mit revalidate“// 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>
)
}
Inkrementelle statische Regeneration (ISR)
Abschnitt betitelt „Inkrementelle statische Regeneration (ISR)“// 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>
}
Client-Komponenten
Abschnitt betitelt „Client-Komponenten“Client-Komponenten verwenden
Abschnitt betitelt „Client-Komponenten verwenden“'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>
)
}
Client-seitiges Datenabrufen
Abschnitt betitelt „Client-seitiges Datenabrufen“'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>
)
}
Bildoptimierung
Abschnitt betitelt „Bildoptimierung“Next.js Image-Komponente verwenden
Abschnitt betitelt „Next.js Image-Komponente verwenden“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}
/>
)
}
Metadaten und SEO
Abschnitt betitelt „Metadaten und SEO“Meta-Tags
Abschnitt betitelt „Meta-Tags“// 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>
}
Dynamische Metadaten
Abschnitt betitelt „Dynamische Metadaten“// 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>
}
Umgebungsvariablen
Abschnitt betitelt „Umgebungsvariablen“Umgebungsvariablen verwenden
Abschnitt betitelt „Umgebungsvariablen verwenden“# .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
Auf Variablen zugreifen
Abschnitt betitelt „Auf Variablen zugreifen“// 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
Abschnitt betitelt „Middleware“Route-Middleware
Abschnitt betitelt „Route-Middleware“// 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*'],
}
Authentifizierungsbeispiel
Abschnitt betitelt „Authentifizierungsbeispiel“Grundlegender Auth-Fluss
Abschnitt betitelt „Grundlegender Auth-Fluss“// 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
}
Datenbankintegration
Abschnitt betitelt „Datenbankintegration“Mit Prisma ORM
Abschnitt betitelt „Mit Prisma ORM“# 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
Prisma in API-Routen verwenden
Abschnitt betitelt „Prisma in API-Routen verwenden“// 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)
}
Bereitstellung
Abschnitt betitelt „Bereitstellung“Vercel-Bereitstellung (empfohlen)
Abschnitt betitelt „Vercel-Bereitstellung (empfohlen)“# Install Vercel CLI
npm i -g vercel
# Deploy
vercel
# Deploy to production
vercel --prod
# Environment variables
vercel env add DATABASE_URL
Selbstgehostete Bereitstellung
Abschnitt betitelt „Selbstgehostete Bereitstellung“# Build for production
npm run build
# Start production server
npm run start
# Or with PM2
pm2 start npm --name "nextjs" -- start
pm2 save
Docker-Bereitstellung
Abschnitt betitelt „Docker-Bereitstellung“# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
Leistungsoptimierung
Abschnitt betitelt „Leistungsoptimierung“Code-Splitting und dynamische Imports
Abschnitt betitelt „Code-Splitting und dynamische Imports“import dynamic from 'next/dynamic'
const HeavyComponent = dynamic(() => import('@/components/Heavy'), {
loading: () => <p>Loading...</p>,
})
export default function Page() {
return <HeavyComponent />
}
Font-Optimierung
Abschnitt betitelt „Font-Optimierung“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>
)
}
Best Practices
Abschnitt betitelt „Best Practices“- 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
Referenzen
Abschnitt betitelt „Referenzen“Last updated: 2026-03-30