Aufgabe 08-1a - Mehrseiter mit Next.js
Lernziele
Abschnitt betitelt „Lernziele“- Du legst ein Next.js-Projekt an und definierst die Seitenstruktur über Ordner.
- Du setzt ein gemeinsames Layout mit Navigation, dynamische Segmente und eine eigene 404-Seite um.
- Du entscheidest begründet zwischen Server- und Client-Komponenten und setzt
"use client"so tief wie möglich. - Du belegst mit einem Experiment und dem Build-Bericht, wo und wann dein Code läuft.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Der (fiktive) Schul-E-Sport-Verein braucht eine Website: Startseite, Team-Übersicht, eine Detailseite je Team, eine Terminliste und eine Über-uns-Seite. Es ist dein erstes echtes Next.js-Projekt, und es begleitet dich mit der Leitfrage des Frameworks: “Wo läuft mein Code, Server oder Client?” (siehe Kapitel Next.js: Struktur und Routing). Die Stufe Wesentlich_überwiegend passt nach Einheit 8.1 (Projekt, Routing und Layouts), die Stufe Wesentlich_vollständig nach Einheit 8.2 (Server- und Client-Komponenten).
Allgemein
Abschnitt betitelt „Allgemein“Projektordner anlegen siehe https://qiz.at/projektordner
-
Lies vorher kurz https://qiz.at/assignmentsabgabe durch.
-
Nur vollständige Abgaben (siehe https://qiz.at/rules) können positiv bewertet werden.
-
Abgabe- und Testdetails siehe https://qiz.at/assignmentsabgabe
-
Die Übung liegt als Unterordner
uebung-08-1ain deinem Jahres-RepositorySJ26_27_4AHITM_SEW_<Benutzername>_exercises. Du legst ihn wie in Einheit 8.1 an und arbeitest allein:Terminal-Fenster npx create-next-app@latest uebung-08-1a --ts --app --biome --no-tailwind --no-src-dir --no-react-compiler --cache-components --import-alias "@/*" --use-npm --yes -
Räum die Startseite der Vorlage auf. Alle Teams und Termine sind erfunden; verwende keine echten Namen von Mitschülerinnen und Mitschülern.
-
Schriftliche Antworten stehen in der
README.mddes Projekts.npm run buildmuss fehlerfrei durchlaufen,npm run lintohne Fehler;node_modules/und.next/kommen nicht ins Repository.
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“- Wurzel-Layout mit Kopfzeile, Navigation und Fußzeile; die Navigation verwendet
Linkund erscheint auf jeder Seite. - Routen
/,/teams,/termineund/ueber-uns, jede Seite mit eigener Überschrift und kurzem Inhalt. - Die Daten liegen als typisierte Arrays in
lib/data.ts, nicht in den Komponenten:interface Team(idals Kurzname für die URL, Name, Spiel, Mitglieder, Spiele, Erfolge) undinterface ClubEvent(Titel, Datum als ISO-String,isHomeMatch), mindestens drei Teams und fünf Termine. /teamslistet alle Teams als verlinkte Karten;/teams/[id]zeigt die Details eines Teams, dieidkommt ausparams.- Während die Detailseite lädt, zeigt eine
loading.tsxim Ordner[id]einen Platzhalter. - Unbekannte IDs führen über
notFound()auf eine selbst gestalteteapp/not-found.tsx.
Tipp:
paramsist ein Promise:const { id } = await params;in einerasync-Seite. Importe auslib/schreibst du mit dem Alias als@/lib/data. Nachif (!team) { notFound(); }weiß TypeScript, dassteamdanach existiert.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
npm run buildundnpm run lintfehlerfrei durchlaufen.- alle vier Routen und die Detailseite erreichbar sind und die Navigation auf jeder Seite mit
Linkarbeitet. - die Daten typisiert in
lib/data.tsliegen und keine Komponente eigene Daten-Arrays enthält. loading.tsxvorhanden ist und eine unbekannte ID die eigene 404-Seite zeigt.
Wie unter Allgemein.
Wesentlich_vollständig
Abschnitt betitelt „Wesentlich_vollständig“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieses Projekts (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Die Terminliste bekommt einen umschaltbaren Filter “nur Heimtermine”. Zerleg nach dem Muster aus Einheit 8.2: Die Seite bleibt Server-Komponente und übergibt die Daten; die Filterkomponente ist Client-Komponente mit
useState. - Hebe in der Navigation den aktiven Link hervor, mit dem Hook
usePathnameausnext/navigation. Begründe in der README in einem Satz, warum das eine Client-Komponente sein muss.
Tipp: Die Navigation wandert dafür aus dem Layout in eine eigene Datei mit
"use client"; das Layout selbst bleibt Server-Komponente. Weil der Pfad erst bei der Anfrage feststeht, verlangt der Build eine<Suspense>-Grenze um die Navigation; alsfallbackeignen sich dieselben Links ohne Hervorhebung. Bei Checkboxen liest duevent.target.checked.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- der Filter funktioniert, die Seite
/termineohne"use client"auskommt und nur die Filterkomponente die Direktive trägt. - der aktive Link hervorgehoben ist, die Navigation eine eigene Client-Komponente ist und die Begründung stimmt.
Wie unter Allgemein.
PlusPlus Aufgabe
Abschnitt betitelt „PlusPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieses Projekts (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Erklär in vier bis sechs Sätzen in der README, warum die Teamliste ohne
"use client"auskommt und der Terminfilter nicht. Nenn das Entscheidungskriterium allgemein. - Experiment: Setz in die Seite
/teams(Server) und in die Filterkomponente (Client) je einconsole.log("rendering <Name>"). Dokumentier mit einer Tabelle und zwei Screenshots, wo die Ausgaben erscheinen (Terminal oder Browser-Konsole), einmal beim direkten Laden der Seite und einmal beim Navigieren über die Navigation.
Tipp: Nicht jede Zeile in der Browser-Konsole stammt aus dem Browser; achte auf die Markierung “Server”. Und überleg, warum eine Client-Komponente auch im Terminal auftaucht.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- die Begründung das allgemeine Kriterium (Hooks, Events, Browser-APIs) nennt.
- die Tabelle beide Fälle (direkt laden, navigieren) für beide Komponenten richtig wiedergibt und die Screenshots sie belegen.
Wie unter Allgemein, dazu die Screenshots im Ordner screenshots/.
MandalorianPlus Aufgabe
Abschnitt betitelt „MandalorianPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieses Projekts (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Gegenprobe: Setz testweise
"use client"auf die Seite/teamsund beobachte, dass alles weiter funktioniert. Erklär in drei Sätzen, warum es trotzdem die schlechtere Lösung ist, und nimm die Direktive wieder heraus. - Lies den Build-Bericht von
npm run build: Welche Routen sind○, welche◐, und warum? Braucht eine deiner Seiten"use cache"oder eine weitere<Suspense>-Grenze? Begründe. - Ergänz ein verschachteltes Layout nur für den Bereich
/teams(etwa eine Unternavigation mit allen Teams) und erklär, wie sich Wurzel- und Bereichs-Layout schachteln.
Tipp: Stichworte für die Gegenprobe: ansteckende Direktive, Client-Bundle, Datenzugriff in Kapitel 9. Für den Build-Bericht hilft die Frage, was Next.js zur Bauzeit noch nicht wissen kann.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- die Gegenprobe durchgeführt, die Direktive wieder entfernt und die Erklärung stichhaltig ist.
- die Einteilung in
○und◐stimmt und die Antwort zu"use cache"und<Suspense>begründet ist. - das Bereichs-Layout nur unter
/teamserscheint und die Schachtelung richtig erklärt ist.
Wie unter Allgemein.
Wissenscheck
Abschnitt betitelt „Wissenscheck“- Wie entsteht in Next.js aus einem Ordner eine Route, und was macht
page.tsxdarin? - Was leistet
Linkgegenüber einem gewöhnlichen<a>? - Welche Fähigkeiten haben nur Client-Komponenten, welche nur Server-Komponenten?
- Warum gehört
"use client"so tief wie möglich in den Komponentenbaum? - Woher weiß eine Seite unter
/teams/[id], welches Team gemeint ist?
Zeit dafür
Abschnitt betitelt „Zeit dafür“Durchschnittlich bis Wesentlich_vollständig: ca. 100 min
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA