366 lines
7.3 KiB
Markdown
366 lines
7.3 KiB
Markdown
# Les 6: Next.js Fundamentals 1 - SSR & Routing
|
|
|
|
---
|
|
|
|
## Hoofdstuk
|
|
**Deel 2: Technical Foundations** (Les 5-9)
|
|
|
|
## Beschrijving
|
|
Introductie tot Next.js voor React developers. Leer wat Server-Side Rendering is, hoe de App Router werkt, en bouw je eerste Next.js applicatie met meerdere pagina's.
|
|
|
|
---
|
|
|
|
## Te Behandelen
|
|
|
|
### Wat is Next.js?
|
|
|
|
**React met superpowers:**
|
|
- React = library voor UI components
|
|
- Next.js = framework dat React complete maakt
|
|
|
|
**Next.js voegt toe:**
|
|
- Routing (geen extra library nodig)
|
|
- Server-Side Rendering (SEO, performance)
|
|
- API routes (backend in je frontend project)
|
|
- Optimalisaties (images, fonts, bundling)
|
|
|
|
---
|
|
|
|
### Server-Side Rendering (SSR) vs Client-Side Rendering (CSR)
|
|
|
|
**Client-Side Rendering (gewone React):**
|
|
```
|
|
1. Browser vraagt pagina
|
|
2. Server stuurt lege HTML + JavaScript
|
|
3. JavaScript laadt in browser
|
|
4. JavaScript rendert de pagina
|
|
5. Gebruiker ziet content
|
|
```
|
|
**Probleem:** Lege pagina tot JS klaar is. Google ziet ook lege pagina.
|
|
|
|
**Server-Side Rendering (Next.js):**
|
|
```
|
|
1. Browser vraagt pagina
|
|
2. Server rendert HTML met content
|
|
3. Browser toont direct de content
|
|
4. JavaScript laadt (hydration)
|
|
5. Pagina wordt interactief
|
|
```
|
|
**Voordeel:** Direct content zichtbaar, beter voor SEO.
|
|
|
|
---
|
|
|
|
### De App Router
|
|
|
|
Next.js 13+ gebruikt de "App Router" met file-based routing:
|
|
|
|
```
|
|
app/
|
|
├── page.tsx → /
|
|
├── about/
|
|
│ └── page.tsx → /about
|
|
├── products/
|
|
│ ├── page.tsx → /products
|
|
│ └── [id]/
|
|
│ └── page.tsx → /products/123
|
|
└── layout.tsx → Wrapper voor alle pagina's
|
|
```
|
|
|
|
**De regel:** Elke `page.tsx` wordt een route!
|
|
|
|
---
|
|
|
|
### Project Aanmaken
|
|
|
|
```bash
|
|
npx create-next-app@latest mijn-app
|
|
|
|
# Antwoorden:
|
|
# ✔ TypeScript? → Yes
|
|
# ✔ ESLint? → Yes
|
|
# ✔ Tailwind CSS? → Yes
|
|
# ✔ `src/` directory? → Yes
|
|
# ✔ App Router? → Yes
|
|
# ✔ Customize import alias? → No
|
|
|
|
cd mijn-app
|
|
npm run dev
|
|
```
|
|
|
|
Open `http://localhost:3000` - je app draait!
|
|
|
|
---
|
|
|
|
### Pagina's Maken
|
|
|
|
**Simpele pagina (`app/about/page.tsx`):**
|
|
```tsx
|
|
export default function AboutPage() {
|
|
return (
|
|
<div className="p-8">
|
|
<h1 className="text-3xl font-bold">Over Ons</h1>
|
|
<p>Welkom op de about pagina!</p>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
Dat is alles! Ga naar `/about` en je ziet je pagina.
|
|
|
|
---
|
|
|
|
### Layouts
|
|
|
|
Layouts wrappen pagina's en blijven behouden tijdens navigatie.
|
|
|
|
**Root Layout (`app/layout.tsx`):**
|
|
```tsx
|
|
export default function RootLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
return (
|
|
<html lang="nl">
|
|
<body>
|
|
<header className="p-4 bg-blue-500 text-white">
|
|
<nav>Mijn App</nav>
|
|
</header>
|
|
<main>{children}</main>
|
|
<footer className="p-4 bg-gray-200">
|
|
© 2024
|
|
</footer>
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Nested Layouts
|
|
|
|
Je kunt layouts nesten voor secties:
|
|
|
|
```
|
|
app/
|
|
├── layout.tsx → Root layout
|
|
├── page.tsx → Homepage
|
|
└── dashboard/
|
|
├── layout.tsx → Dashboard layout (sidebar)
|
|
└── page.tsx → Dashboard pagina
|
|
```
|
|
|
|
**Dashboard Layout (`app/dashboard/layout.tsx`):**
|
|
```tsx
|
|
export default function DashboardLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
return (
|
|
<div className="flex">
|
|
<aside className="w-64 bg-gray-100 p-4">
|
|
<nav>Sidebar hier</nav>
|
|
</aside>
|
|
<div className="flex-1">{children}</div>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Dynamic Routes
|
|
|
|
Voor pagina's met parameters zoals `/products/123`:
|
|
|
|
**Folder structuur:**
|
|
```
|
|
app/products/[id]/page.tsx
|
|
```
|
|
|
|
**De pagina:**
|
|
```tsx
|
|
interface Props {
|
|
params: { id: string }
|
|
}
|
|
|
|
export default function ProductPage({ params }: Props) {
|
|
return (
|
|
<div>
|
|
<h1>Product {params.id}</h1>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
Nu werkt `/products/1`, `/products/abc`, etc.
|
|
|
|
---
|
|
|
|
### Link Component
|
|
|
|
Gebruik `Link` voor client-side navigatie (snel, geen page reload):
|
|
|
|
```tsx
|
|
import Link from 'next/link'
|
|
|
|
export default function Navigation() {
|
|
return (
|
|
<nav className="flex gap-4">
|
|
<Link href="/">Home</Link>
|
|
<Link href="/about">About</Link>
|
|
<Link href="/products">Products</Link>
|
|
<Link href="/products/123">Product 123</Link>
|
|
</nav>
|
|
)
|
|
}
|
|
```
|
|
|
|
**Niet doen:**
|
|
```tsx
|
|
// ❌ Dit werkt maar is langzamer
|
|
<a href="/about">About</a>
|
|
```
|
|
|
|
---
|
|
|
|
### Special Files
|
|
|
|
Next.js heeft speciale bestanden:
|
|
|
|
| File | Doel |
|
|
|------|------|
|
|
| `page.tsx` | De pagina content |
|
|
| `layout.tsx` | Wrapper, blijft behouden |
|
|
| `loading.tsx` | Loading state |
|
|
| `error.tsx` | Error boundary |
|
|
| `not-found.tsx` | 404 pagina |
|
|
|
|
**Loading state (`app/products/loading.tsx`):**
|
|
```tsx
|
|
export default function Loading() {
|
|
return <div>Laden...</div>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Metadata (SEO)
|
|
|
|
Voeg metadata toe per pagina:
|
|
|
|
```tsx
|
|
import type { Metadata } from 'next'
|
|
|
|
export const metadata: Metadata = {
|
|
title: 'Over Ons | Mijn App',
|
|
description: 'Lees meer over ons bedrijf',
|
|
}
|
|
|
|
export default function AboutPage() {
|
|
return <h1>Over Ons</h1>
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Tools
|
|
- Next.js 14
|
|
- TypeScript
|
|
- Tailwind CSS
|
|
- OpenCode/WebStorm
|
|
- Vercel
|
|
|
|
---
|
|
|
|
## Lesopdracht (2 uur)
|
|
|
|
### Bouw Multi-Page Next.js App
|
|
|
|
**Deel 1: Project Setup (20 min)**
|
|
|
|
1. `npx create-next-app@latest my-shop` (TypeScript + Tailwind + App Router)
|
|
2. Open in editor
|
|
3. `npm run dev`
|
|
4. Verifieer: `localhost:3000` werkt
|
|
|
|
**Deel 2: Pagina's Maken (40 min)**
|
|
|
|
Maak deze pagina's:
|
|
1. `/` - Homepage met welkomstbericht
|
|
2. `/about` - Over ons pagina
|
|
3. `/products` - Producten overzicht
|
|
4. `/contact` - Contact pagina
|
|
|
|
Elke pagina moet unieke content hebben.
|
|
|
|
**Deel 3: Layout met Navigatie (30 min)**
|
|
|
|
1. Maak Header component met navigatie (gebruik Link)
|
|
2. Maak Footer component
|
|
3. Voeg beide toe aan root layout
|
|
4. Test: navigatie werkt zonder page reload
|
|
|
|
**Deel 4: Dynamic Route (30 min)**
|
|
|
|
1. Maak `/products/[id]` route
|
|
2. Toon product ID op de pagina
|
|
3. Maak links naar `/products/1`, `/products/2`, `/products/3`
|
|
4. Test: alle links werken
|
|
|
|
**Bonus:** Voeg `loading.tsx` toe aan products folder
|
|
|
|
### Deliverable
|
|
- Werkende Next.js app met 4+ pagina's
|
|
- Navigatie met Link component
|
|
- Dynamic route die werkt
|
|
- Deploy naar Vercel
|
|
|
|
---
|
|
|
|
## Huiswerk (2 uur)
|
|
|
|
### Uitbreiden en Verdiepen
|
|
|
|
**Deel 1: Nested Layout (45 min)**
|
|
|
|
1. Maak `/dashboard` section met eigen layout
|
|
2. Dashboard layout heeft sidebar
|
|
3. Maak `/dashboard/settings` en `/dashboard/profile` pagina's
|
|
4. Test: sidebar blijft bij navigatie binnen dashboard
|
|
|
|
**Deel 2: Special Files (45 min)**
|
|
|
|
1. Maak `loading.tsx` voor products (toon "Laden...")
|
|
2. Maak `error.tsx` voor products (toon error message)
|
|
3. Maak `not-found.tsx` in app root (custom 404)
|
|
4. Test elk van deze states
|
|
|
|
**Deel 3: Metadata (30 min)**
|
|
|
|
1. Voeg metadata toe aan elke pagina (title, description)
|
|
2. Bekijk in browser: `<head>` toont juiste meta tags
|
|
3. Test met Lighthouse: SEO score
|
|
|
|
### Deliverable
|
|
- App met nested layouts
|
|
- Special files (loading, error, not-found)
|
|
- Metadata op elke pagina
|
|
- Screenshot van Lighthouse SEO score
|
|
|
|
---
|
|
|
|
## Leerdoelen
|
|
Na deze les kan de student:
|
|
- Uitleggen wat Next.js toevoegt aan React
|
|
- Het verschil tussen SSR en CSR beschrijven
|
|
- Een Next.js project opzetten met App Router
|
|
- Pagina's maken met file-based routing
|
|
- Layouts gebruiken voor herhalende elementen
|
|
- Dynamic routes maken met parameters
|
|
- Link component gebruiken voor navigatie
|
|
- Special files toepassen (loading, error, not-found)
|
|
- Metadata toevoegen voor SEO
|