Appearance
Kapitel 5: Seiten & Komponenten
📖 Lernziele
In diesem Kapitel lernen Sie:
- ✅ Seitenkomponenten erstellen (page.js)
- ✅ Layout-Komponenten verwenden (layout.js)
- ✅ Eigene Komponenten entwickeln und verwenden
- ✅ Statische Assets verarbeiten (Bilder, Fonts, CSS)
- ✅ Metadaten für SEO konfigurieren
5.1 Seitenkomponenten (page.js)
🎯 Was ist eine Seitenkomponente?
Jede page.js Datei definiert den Inhalt einer Route.
Beispiel: app/page.js (Startseite)
jsx
// Server Component (Standard)
export default function HomePage() {
return (
<main>
<h1>Willkommen auf meiner Next.js Seite</h1>
<p>Dies ist die Startseite.</p>
</main>
);
}📝 Seite mit Client-Interaktivität
Wenn Sie Hooks oder Event-Handler benötigen:
jsx
'use client'; // WICHTIG: Macht es zu einer Client Component
import { useState } from 'react';
export default function HomePage() {
const [count, setCount] = useState(0);
return (
<main>
<h1>Zähler: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Erhöhen
</button>
</main>
);
}⚡ Server vs Client Components
| Aspekt | Server Component | Client Component |
|---|---|---|
| Directive | Keine | 'use client' |
| Hooks | ❌ Nicht verfügbar | ✅ Verfügbar |
| Event Handler | ❌ Nicht verfügbar | ✅ Verfügbar |
| Datenabfrage | ✅ Direkt (async/await) | ⚠️ Über API |
5.2 Layout-Komponenten (layout.js)
🎯 Was ist ein Layout?
Ein Layout ist eine gemeinsame Struktur, die auf mehreren Seiten angezeigt wird (z.B. Header, Footer, Sidebar).
📝 Root Layout (app/layout.js)
Datei: app/layout.js
jsx
export const metadata = {
title: 'Meine Next.js Seite',
description: 'Eine tolle Webseite mit Next.js',
};
export default function RootLayout({ children }) {
return (
<html lang="de">
<body>
<header style={{ padding: '20px', background: '#f0f0f0' }}>
<nav>
<Link href="/">Start</Link> |{' '}
<Link href="/about">Über uns</Link>
</nav>
</header>
<main style={{ padding: '20px' }}>
{children}
</main>
<footer style={{ padding: '20px', background: '#333', color: 'white' }}>
<p>© 2024 Meine Firma</p>
</footer>
</body>
</html>
);
}🌐 Verschachtelte Layouts
Szenario: Dashboard mit eigenem Layout.
Datei: app/dashboard/layout.js
jsx
export default function DashboardLayout({ children }) {
return (
<div style={{ display: 'flex' }}>
{/* Sidebar */}
<aside style={{ width: '250px', background: '#f8f9fa', padding: '20px' }}>
<h3>Dashboard</h3>
<nav>
<ul>
<li><a href="/dashboard">Übersicht</a></li>
<li><a href="/dashboard/settings">Einstellungen</a></li>
</ul>
</nav>
</aside>
{/* Inhalt */}
<section style={{ flex: 1, padding: '20px' }}>
{children}
</section>
</div>
);
}5.3 Komponentenentwicklung
🎯 Eigene Komponenten erstellen
Datei: components/Button.js
jsx
export default function Button({ children, onClick, variant = 'primary' }) {
const styles = {
primary: { background: 'blue', color: 'white' },
secondary: { background: 'gray', color: 'white' },
};
return (
<button
onClick={onClick}
style={{
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
...styles[variant],
}}
>
{children}
</button>
);
}📝 Verwendung der Komponente
In einer Seite:
jsx
import Button from '@/components/Button';
export default function HomePage() {
return (
<div>
<Button onClick={() => alert('Geklickt!')}>
Klick mich
</Button>
<Button variant="secondary" onClick={() => console.log('Secondary')}>
Abbrechen
</Button>
</div>
);
}🔗 Props übergeben
Elternkomponente:
jsx
<Card
title="Mein Titel"
description="Beschreibung..."
onAction={() => console.log('Aktion!')}
/>Kindkomponente (Card.js):
jsx
export default function Card({ title, description, onAction }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{description}</p>
<button onClick={onAction}>Aktion</button>
</div>
);
}5.4 Automatischer Import & globale Registrierung
🎯 Next.js Komponenten-Auto-Import
Next.js unterstützt keinen automatischen Import von Komponenten. Sie müssen sie manuell importieren:
jsx
// ❌ Funktioniert nicht (muss importiert werden)
<Button>Klick</Button>
// ✅ Korrekt
import Button from '@/components/Button';
<Button>Klick</Button>📝 Import-Aliase konfigurieren
In jsconfig.json oder tsconfig.json:
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}Verwendung:
jsx
import Button from '@/components/Button'; // ✅ Alias
import Button from '../../components/Button'; // ❌ Relativer Pfad (unschön)5.5 Statische Assets verarbeiten
🖼️ Bilder (Image-Komponente)
Import: next/image
Beispiel:
jsx
import Image from 'next/image';
import logo from '@/public/logo.png';
export default function HomePage() {
return (
<div>
{/* Lokales Bild */}
<Image
src={logo}
alt="Logo"
width={200}
height={100}
/>
{/* Remote Bild */}
<Image
src="https://example.com/bild.jpg"
alt="Remote Bild"
width={500}
height={300}
/>
</div>
);
}⚙️ next.config.js für Bilder
javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
domains: ['example.com', 'via.placeholder.com'],
},
};
module.exports = nextConfig;🔤 Fonts (next/font)
Google Fonts verwenden:
jsx
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
export default function RootLayout({ children }) {
return (
<html lang="de" className={inter.className}>
<body>{children}</body>
</html>
);
}Lokale Fonts:
javascript
import localFont from 'next/font/local';
const myFont = localFont({ src: './my-font.woff2' });5.6 Metadaten konfigurieren (SEO)
🎯 Metadata-Objekt (Static)
In layout.js oder page.js:
jsx
export const metadata = {
title: 'Meine Next.js Seite',
description: 'Eine tolle Webseite mit Next.js 14',
keywords: ['Next.js', 'React', 'Webentwicklung'],
};
export default function RootLayout({ children }) {
return (
<html lang="de">
<body>{children}</body>
</html>
);
}🎯 Generate Metadata (Dynamic)
Für dynamische Seiten (z.B. Blog-Artikel):
jsx
import { generateMetadata } from 'next/dist/lib/metadata';
export async function generateMetadata({ params }) {
const post = await getBlogPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
images: [post.coverImage],
},
};
}
export default function BlogPost({ params }) {
// ...
}📝 SEO-Optimierung
| Meta-Tag | Zweck | Beispiel |
|---|---|---|
title | Browser-Tab Titel | "Meine Seite - Home" |
description | Suchergebnis-Beschreibung | "Die beste Seite für..." |
keywords | Suchbegriffe | ["Next.js", "Tutorial"] |
openGraph | Social Media Vorschau | Bild, Titel, Beschreibung |
📝 Zusammenfassung
In diesem Kapitel haben Sie gelernt:
| Konzept | Erklärung |
|---|---|
| Seitenkomponenten | page.js für Routen-Inhalt |
| Layouts | layout.js für gemeinsame Struktur |
| Komponenten | Wiederverwendbare UI-Elemente |
| Statische Assets | Bilder (next/image), Fonts (next/font) |
| Metadaten | SEO-Optimierung (metadata Objekt) |
✅ Nächste Schritte
- ✅ Übung: Erstellen Sie eine wiederverwendbare Button-Komponente
- ✅ Übung: Konfigurieren Sie Metadaten für besseres SEO
- ✅ Weiter geht's: Kapitel 6 - Server & Client Components
🎯 Selbsttest
Frage 1: Welche Datei definiert den Inhalt einer Route?
Antwort anzeigen
`page.js`Frage 2: Wie aktiviert man Client-Side-Funktionalität in einer Komponente?
Antwort anzeigen
Durch Hinzufügen der Directive `'use client';` am Anfang der Datei.Frage 3: Welche Komponente wird für optimierte Bilder verwendet?
Antwort anzeigen
`next/image` (Image-Komponente)🚀 Weiter zu Kapitel 6: Server & Client Components
