W Metropolii Quantum, inżynierowie projektują zaawansowane systemy transportu, które mogą działać zarówno na klasycznych drogach, jak i na nowych szlakach kwantowej teleportacji. Podobnie, Next.js oferuje dwa równoległe systemy routingu: tradycyjny Pages Router i nowoczesny App Router. W tym module szczegółowo przeanalizujemy różnice między tymi dwoma podejściami i zrozumiemy, jak organizować pliki i katalogi w naszych projektach.
Next.js pierwotnie opierał się na konwencji routingu opartej na katalogach w folderze
pages/. W Next.js 13, wprowadzono nowy system routingu oparty na folderze app/. Ta ewolucja przypomina przejście od klasycznych systemów transportu do kwantowej teleportacji w Metropolii Quantum - nowa technologia jest bardziej zaawansowana, ale obie nadal współistnieją.Pages Router to oryginalny system routingu w Next.js. Jest prosty, dobrze udokumentowany i nadal szeroko używany. W tej konwencji każdy plik JavaScript lub TypeScript w katalogu
pages/ automatycznie staje się ścieżką w aplikacji.1pages/
2├── index.js # Trasa: /
3├── about.js # Trasa: /about
4├── contact.tsx # Trasa: /contact
5├── products/
6│ ├── index.js # Trasa: /products
7│ └── [id].js # Trasa: /products/:id (dynamiczna)
8└── api/
9 └── hello.js # Endpoint API: /api/helloW tym systemie:
[param]api/ służy do obsługi endpointów APIApp Router, wprowadzony w Next.js 13 i dopracowany w wersji 15, reprezentuje nowe podejście oparte na React Server Components. Jest to jak przejście od tradycyjnych pojazdów do teleportacji kwantowej - fundamentalna zmiana w sposobie myślenia o aplikacjach webowych.
1app/
2├── layout.tsx # Główny układ (wymagany)
3├── page.tsx # Trasa: /
4├── about/
5│ └── page.tsx # Trasa: /about
6├── blog/
7│ ├── page.tsx # Trasa: /blog
8│ ├── layout.tsx # Układ specyficzny dla /blog i jego podścieżek
9│ └── [slug]/
10│ └── page.tsx # Trasa: /blog/:slug (dynamiczna)
11└── api/
12 └── users/
13 └── route.ts # Endpoint API: /api/usersW App Router:
page.tsx renderuje komponent strony dla danej ścieżkilayout.tsx definiuje współdzielony układ dla wszystkich stron w katalogu i jego podkatalogach[param]route.tsApp Router wprowadza "konwencję ponad konfiguracją" z szeregiem specjalnych plików, które mają określone role. Jest to jak wyspecjalizowane moduły w systemach Metropolii Quantum - każdy z określoną funkcją w ogólnej architekturze.
page.tsx: Renderuje interfejs użytkownika trasy i sprawia, że ścieżka jest publicznie dostępna.
1// app/dashboard/page.tsx
2export default function DashboardPage() {
3 return (
4 <section>
5 <h1>Panel kontrolny Metropolii Quantum</h1>
6 <p>Witaj w centrum dowodzenia!</p>
7 </section>
8 );
9}layout.tsx: Definiuje współdzielony interfejs dla segmentu i jego dzieci.
1// app/dashboard/layout.tsx
2export default function DashboardLayout({
3 children,
4}: {
5 children: React.ReactNode;
6}) {
7 return (
8 <div className="dashboard-layout">
9 <nav className="dashboard-sidebar">
10 {/* Nawigacja panelu bocznego */}
11 </nav>
12 <main className="dashboard-main">{children}</main>
13 </div>
14 );
15}route.ts: Tworzy endpoint API przy użyciu nowego API obsługi żądań.
1// app/api/status/route.ts
2import { NextResponse } from 'next/server';
3
4export async function GET() {
5 return NextResponse.json({
6 status: 'online',
7 systemsOperational: 15,
8 time: new Date().toISOString()
9 });
10}
11
12export async function POST(request: Request) {
13 const data = await request.json();
14 // Przetwarzanie danych...
15 return NextResponse.json({ success: true });
16}loading.tsx: Tworzy interfejs ładowania z React Suspense.
1// app/dashboard/loading.tsx
2export default function DashboardLoading() {
3 return (
4 <div className="dashboard-loading">
5 <div className="spinner"></div>
6 <p>Ładowanie danych systemowych Metropolii...</p>
7 </div>
8 );
9}error.tsx: Tworzy interfejs obsługi błędów z React Error Boundary.
1'use client'; // Komponenty obsługi błędów muszą być komponentami klienckimi
2
3import { useEffect } from 'react';
4
5export default function DashboardError({
6 error,
7 reset,
8}: {
9 error: Error;
10 reset: () => void;
11}) {
12 useEffect(() => {
13 // Logowanie błędu do systemu monitorowania
14 console.error(error);
15 }, [error]);
16
17 return (
18 <div className="error-container">
19 <h2>Wystąpił błąd w systemach Metropolii!</h2>
20 <p>{error.message}</p>
21 <button onClick={reset}>Spróbuj ponownie</button>
22 </div>
23 );
24}not-found.tsx: Tworzy interfejs dla nieznalezionego zasobu (404).
1// app/not-found.tsx
2export default function NotFound() {
3 return (
4 <div className="not-found">
5 <h2>Strefa nieznana</h2>
6 <p>Nie znaleziono modułu Metropolii Quantum o takim identyfikatorze.</p>
7 <a href="/">Powrót do centrum dowodzenia</a>
8 </div>
9 );
10}App Router wprowadza kilka zaawansowanych funkcji organizacyjnych, które przypominają zaawansowane systemy transportu w Metropolii Quantum - pozwalają na bardziej skomplikowane i elastyczne trasy.
Grupy tras pozwalają na organizowanie plików bez wpływania na strukturę URL. Są oznaczane przez ujęcie nazwy katalogu w nawiasy:
(nazwa-grupy).1app/
2├── (marketing)/ # Grupa tras (nie wpływa na ścieżkę URL)
3│ ├── about/
4│ │ └── page.tsx # Trasa: /about
5│ └── contact/
6│ └── page.tsx # Trasa: /contact
7└── (dashboard)/ # Inna grupa tras
8 ├── layout.tsx # Współdzielony układ dla tras dashboard
9 ├── page.tsx # Trasa: /
10 └── stats/
11 └── page.tsx # Trasa: /statsGrupy tras są jak dzielnice w Metropolii Quantum - pomagają organizować strukturę miasta, ale niekoniecznie wpływają na adresy.
Trasy równoległe pozwalają na równoczesne renderowanie wielu stron w tym samym widoku, co jest przydatne dla złożonych układów. Są oznaczane przez nazwę slotu ze znakiem "@":
@nazwa-slotu.1app/
2├── layout.tsx # Główny układ
3├── page.tsx # Główna strona
4└── dashboard/
5 ├── layout.tsx # Układ z wieloma slotami
6 │ // layout.tsx definiuje sloty {children, @stats, @notifications}
7 ├── page.tsx # Domyślna zawartość dla slotu głównego
8 ├── @stats/
9 │ └── page.tsx # Zawartość dla slotu @stats
10 └── @notifications/
11 └── page.tsx # Zawartość dla slotu @notifications1// app/dashboard/layout.tsx
2export default function DashboardLayout({
3 children,
4 stats,
5 notifications,
6}: {
7 children: React.ReactNode;
8 stats: React.ReactNode;
9 notifications: React.ReactNode;
10}) {
11 return (
12 <div className="dashboard-grid">
13 <main>{children}</main>
14 <aside className="stats-panel">{stats}</aside>
15 <section className="notifications-panel">{notifications}</section>
16 </div>
17 );
18}Trasy równoległe to jak równoległe wymiary w Metropolii Quantum - różne rzeczywistości dostępne jednocześnie.
Pozwalają na "przechwycenie" trasy i wyświetlenie jej inaczej, co jest idealne dla modali, które zachowują kontekst nawigacji. Są oznaczane przez nazwę segmentu z znakiem "(.)":
(.)nazwa, (..)nazwa lub (...)nazwa.1app/
2├── layout.tsx
3├── page.tsx # Trasa: /
4└── dashboard/
5 ├── layout.tsx
6 ├── page.tsx # Trasa: /dashboard
7 └── projects/
8 ├── page.tsx # Trasa: /dashboard/projects
9 ├── [id]/
10 │ └── page.tsx # Trasa: /dashboard/projects/:id
11 └── (.)create/ # Przechwytuje /dashboard/projects/create
12 └── page.tsx # Wyświetlane jako modal nad /dashboard/projectsPrzechwytujące trasy są jak kwantowe skróty w Metropolii Quantum - pozwalają na szybki dostęp do zasobów bez zmiany kontekstu.
Oprócz struktury routingu, Next.js 15 sugeruje określone sposoby organizacji kodu. Jest to jak planowanie dzielnic w Metropolii Quantum - właściwa organizacja zwiększa efektywność i czytelność.
Komponenty, które są używane w wielu miejscach, powinny być zorganizowane w spójny sposób. Oto zalecana struktura:
1src/
2├── app/ # Aplikacja z App Router
3│ ├── layout.tsx
4│ └── page.tsx
5├── components/ # Współdzielone komponenty
6│ ├── ui/ # Podstawowe komponenty UI
7│ │ ├── Button.tsx
8│ │ └── Card.tsx
9│ └── features/ # Komponenty specyficzne dla funkcji
10│ ├── dashboard/
11│ └── auth/
12├── lib/ # Współdzielone funkcje i klasy
13│ ├── api/
14│ └── utils/
15├── hooks/ # Niestandardowe hooki React
16│ ├── useAuth.ts
17│ └── useLocalStorage.ts
18└── styles/ # Style globalne
19 └── globals.cssNext.js 15 i App Router wspierają podejście "co-location", gdzie pliki związane z konkretną trasą są umieszczane blisko siebie. Jest to jak mikrodystrykty w Metropolii Quantum - wszystko, czego potrzebujesz, jest blisko.
1app/
2└── dashboard/
3 ├── page.tsx
4 ├── loading.tsx # Ładowanie dla tej trasy
5 ├── error.tsx # Obsługa błędów dla tej trasy
6 ├── layout.tsx # Układ dla tej trasy
7 ├── actions.ts # Server Actions dla tej trasy
8 ├── components/ # Komponenty specyficzne dla tej trasy
9 │ ├── StatusCard.tsx
10 │ └── DashboardNav.tsx
11 └── styles/ # Style specyficzne dla tej trasy
12 └── dashboard.module.cssTeraz, gdy poznaliśmy oba systemy routingu, porównajmy je - podobnie jak inżynierowie Metropolii Quantum mogliby porównywać klasyczny transport z teleportacją kwantową.
Pages Router:
App Router:
Pages Router:
App Router:
Pages Router:
App Router:
Pages Router:
App Router:
Wybór między App Router a Pages Router przypomina wybór między kwantową teleportacją a tradycyjnym transportem w Metropolii Quantum - zależy od konkretnych potrzeb.
Jeśli masz istniejący projekt używający Pages Router, możesz stopniowo migrować do App Router. Jest to jak modernizacja dzielnic w Metropolii Quantum - nie musisz przebudowywać wszystkiego naraz.
Next.js 15 pozwala na współistnienie obu systemów. Możesz zacząć używać
app/ dla nowych funkcji, jednocześnie zachowując istniejące strony w pages/.1.
2├── app/ # Nowe funkcje używające App Router
3│ ├── new-feature/
4│ │ └── page.tsx # /new-feature
5│ └── layout.tsx
6└── pages/ # Istniejące strony używające Pages Router
7 ├── index.js # /
8 └── about.js # /aboutWażne uwagi dotyczące migracji:
app/ mają priorytet nad ścieżkami w pages/pages/ do app/Niezależnie od wybranego systemu routingu, warto trzymać się pewnych najlepszych praktyk:
Struktura zorientowana na funkcje: Organizuj komponenty i kod wokół funkcji biznesowych, a nie według typów technicznych.
1src/
2├── features/
3│ ├── auth/
4│ │ ├── components/
5│ │ ├── hooks/
6│ │ └── utils/
7│ └── dashboard/
8│ ├── components/
9│ ├── hooks/
10│ └── utils/Modułowe podejście: Traktuj każdą funkcjonalność jako izolowany moduł z jasno określonym API.
Spójna konwencja nazewnictwa: Ustal konwencje i trzymaj się ich w całym projekcie.
Importy względne vs. absolutne: Używaj aliasów importu (
@/) dla lepszej czytelności i łatwiejszego przenoszenia plików.Kolokacja testów: Umieszczaj testy blisko testowanych komponentów.
1src/
2├── components/
3│ ├── Button.tsx
4│ └── Button.test.tsxStruktura katalogów i plików w Next.js 15 jest jak architektura Metropolii Quantum - z odpowiednim planowaniem może być zarówno elegancka, jak i funkcjonalna. App Router wprowadza bardziej zaawansowany, ale także bardziej elastyczny model organizacji aplikacji, podczas gdy Pages Router oferuje prostsze i bardziej bezpośrednie podejście.
Wybór między nimi zależy od specyficznych potrzeb projektu, ale w nowych projektach zaleca się korzystanie z App Router, aby wykorzystać najnowsze funkcje i optymalizacje. Pamiętaj, że dobra organizacja projektu to klucz do łatwej konserwacji i rozszerzalności w przyszłości.
W kolejnym module zagłębimy się w system komponentów Next.js 15, szczególnie różnice między Client Components a Server Components, które są fundamentalną częścią App Router.