Polski

Odkryj moc App Routera w Next.js dzięki naszemu szczegółowemu przewodnikowi po routingu opartym na plikach. Naucz się strukturyzować aplikację, tworzyć dynamiczne ścieżki, zarządzać layoutami i nie tylko.

App Router w Next.js: Kompleksowy przewodnik po routingu opartym na plikach

App Router w Next.js, wprowadzony w wersji 13 i stający się standardem w późniejszych wersjach, rewolucjonizuje sposób, w jaki tworzymy strukturę i nawigację w aplikacjach. Wprowadza on potężny i intuicyjny system routingu oparty na plikach, który upraszcza rozwój, poprawia wydajność i zwiększa ogólne doświadczenie dewelopera. Ten kompleksowy przewodnik zagłębi się w routing oparty na plikach w App Routerze, dostarczając wiedzy i umiejętności do budowania solidnych i skalowalnych aplikacji Next.js.

Czym jest routing oparty na plikach?

Routing oparty na plikach to system, w którym struktura ścieżek aplikacji jest bezpośrednio determinowana przez organizację plików i katalogów. W App Routerze Next.js definiujesz ścieżki, tworząc pliki w katalogu `app`. Każdy folder reprezentuje segment ścieżki, a specjalne pliki w tych folderach definiują, jak dany segment będzie obsługiwany. Takie podejście oferuje kilka zalet:

Pierwsze kroki z App Routerem

Aby używać App Routera, musisz utworzyć nowy projekt Next.js lub zmigrować istniejący projekt. Upewnij się, że używasz Next.js w wersji 13 lub nowszej.

Tworzenie nowego projektu:

Możesz utworzyć nowy projekt Next.js z App Routerem, używając następującego polecenia:

npx create-next-app@latest my-app --example with-app

Migracja istniejącego projektu:

Aby zmigrować istniejący projekt, musisz przenieść swoje strony z katalogu `pages` do katalogu `app`. Może być konieczne dostosowanie logiki routingu. Next.js dostarcza przewodnik migracji, który pomoże Ci w tym procesie.

Podstawowe koncepcje routingu opartego na plikach

App Router wprowadza kilka specjalnych plików i konwencji, które definiują, jak obsługiwane są Twoje ścieżki:

1. Katalog `app`

Katalog `app` jest korzeniem ścieżek Twojej aplikacji. Wszystkie pliki i foldery w tym katalogu będą używane do generowania ścieżek. Wszystko, co znajduje się poza katalogiem `app` (jak katalog `pages`, jeśli migrujesz), będzie ignorowane przez App Router.

2. Plik `page.js`

Plik `page.js` (lub `page.jsx`, `page.ts`, `page.tsx`) jest najbardziej fundamentalną częścią App Routera. Definiuje on komponent UI, który będzie renderowany dla określonego segmentu ścieżki. Jest to **wymagany** plik dla każdego segmentu ścieżki, do którego chcesz mieć bezpośredni dostęp.

Przykład:

Jeśli masz strukturę plików taką jak ta:

app/
  about/
    page.js

Komponent eksportowany z `app/about/page.js` zostanie wyrenderowany, gdy użytkownik przejdzie do `/about`.

// app/about/page.js
import React from 'react';

export default function AboutPage() {
  return (
    <div>
      <h1>O nas</h1>
      <p>Dowiedz się więcej o naszej firmie.</p>
    </div>
  );
}

3. Plik `layout.js`

Plik `layout.js` (lub `layout.jsx`, `layout.ts`, `layout.tsx`) definiuje interfejs użytkownika, który jest współdzielony przez wiele stron w ramach segmentu ścieżki. Layouty są przydatne do tworzenia spójnych nagłówków, stopek, pasków bocznych i innych elementów, które powinny być obecne na wielu stronach.

Przykład:

Załóżmy, że chcesz dodać nagłówek zarówno do strony `/about`, jak i hipotetycznej strony `/about/team`. Możesz utworzyć plik `layout.js` w katalogu `app/about`:

// app/about/layout.js
import React from 'react';

export default function AboutLayout({ children }) {
  return (
    <div>
      <header>
        <h1>O naszej firmie</h1>
      </header>
      <main>{children}</main>
    </div>
  );
}

Właściwość `children` zostanie zastąpiona przez interfejs użytkownika renderowany przez plik `page.js` w tym samym katalogu lub w dowolnych zagnieżdżonych katalogach.

4. Plik `template.js`

Plik `template.js` jest podobny do `layout.js`, ale tworzy nową instancję komponentu dla każdej podrzędnej ścieżki. Jest to przydatne w scenariuszach, w których chcesz zachować stan komponentu lub zapobiec ponownym renderowaniom podczas nawigacji między podrzędnymi ścieżkami. W przeciwieństwie do layoutów, szablony będą renderowane ponownie przy nawigacji. Używanie szablonów jest świetne do animowania elementów podczas nawigacji.

Przykład:

// app/template.js
'use client'

import { useState } from 'react'

export default function Template({ children }) {
  const [count, setCount] = useState(0)

  return (
    <main>
      <p>Szablon: {count}</p>
      <button onClick={() => setCount(count + 1)}>Zaktualizuj szablon</button>
      {children}
    </main>
  )
}

5. Plik `loading.js`

Plik `loading.js` (lub `loading.jsx`, `loading.ts`, `loading.tsx`) pozwala na stworzenie interfejsu ładowania, który jest wyświetlany podczas wczytywania segmentu ścieżki. Jest to przydatne do zapewnienia lepszego doświadczenia użytkownika podczas pobierania danych lub wykonywania innych operacji asynchronicznych.

Przykład:

// app/about/loading.js
import React from 'react';

export default function Loading() {
  return <p>Ładowanie informacji o firmie...</p>;
}

Gdy użytkownik przejdzie do `/about`, komponent `Loading` będzie wyświetlany, dopóki komponent `page.js` nie zostanie w pełni wyrenderowany.

6. Plik `error.js`

Plik `error.js` (lub `error.jsx`, `error.ts`, `error.tsx`) pozwala na stworzenie niestandardowego interfejsu błędu, który jest wyświetlany, gdy wystąpi błąd w segmencie ścieżki. Jest to przydatne do dostarczania bardziej przyjaznego komunikatu o błędzie i zapobiegania awarii całej aplikacji.

Przykład:

// app/about/error.js
'use client'

import React from 'react';

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Wystąpił błąd!</h2>
      <p>{error.message}</p>
      <button onClick={() => reset()}>Spróbuj ponownie</button>
    </div>
  );
}

Jeśli podczas renderowania strony `/about` wystąpi błąd, zostanie wyświetlony komponent `Error`. Właściwość `error` zawiera informacje o błędzie, a funkcja `reset` pozwala użytkownikowi spróbować przeładować stronę.

7. Grupy Ścieżek (Route Groups)

Grupy Ścieżek `(nazwaGrupy)` pozwalają organizować ścieżki bez wpływu na strukturę URL. Tworzy się je, otaczając nazwę folderu nawiasami. Jest to szczególnie pomocne przy organizowaniu layoutów i współdzielonych komponentów.

Przykład:

app/
  (marketing)/
    about/
      page.js
    contact/
      page.js
  (shop)/
    products/
      page.js

W tym przykładzie strony `about` i `contact` są zgrupowane w grupie `marketing`, a strona `products` jest w grupie `shop`. Adresy URL pozostają odpowiednio `/about`, `/contact` i `/products`.

8. Dynamiczne Ścieżki

Dynamiczne ścieżki pozwalają tworzyć ścieżki ze zmiennymi segmentami. Jest to przydatne do wyświetlania treści na podstawie danych pobranych z bazy danych lub API. Segmenty dynamicznych ścieżek definiuje się, otaczając nazwę segmentu nawiasami kwadratowymi (np. `[id]`).

Przykład:

Załóżmy, że chcesz utworzyć ścieżkę do wyświetlania pojedynczych wpisów na blogu na podstawie ich ID. Możesz utworzyć taką strukturę plików:

app/
  blog/
    [id]/
      page.js

Segment `[id]` jest segmentem dynamicznym. Komponent eksportowany z `app/blog/[id]/page.js` zostanie wyrenderowany, gdy użytkownik przejdzie pod adres URL taki jak `/blog/123` lub `/blog/456`. Wartość parametru `id` będzie dostępna we właściwości `params` komponentu.

// app/blog/[id]/page.js
import React from 'react';

export default async function BlogPost({ params }) {
  const { id } = params;

  // Pobierz dane dla wpisu na blogu o danym ID
  const post = await fetchBlogPost(id);

  if (!post) {
    return <p>Nie znaleziono wpisu na blogu.</p>;
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </div>
  );
}

async function fetchBlogPost(id) {
  // Symulacja pobierania danych z bazy danych lub API
  return new Promise((resolve) => {
    setTimeout(() => {
      const posts = {
        '123': { title: 'Mój pierwszy wpis na blogu', content: 'To jest treść mojego pierwszego wpisu na blogu.' },
        '456': { title: 'Kolejny wpis na blogu', content: 'To jest jakaś inna ekscytująca treść.' },
      };
      resolve(posts[id] || null);
    }, 500);
  });
}

Możesz również używać wielu dynamicznych segmentów w jednej ścieżce. Na przykład, możesz mieć ścieżkę taką jak `/blog/[category]/[id]`.

9. Segmenty Catch-all

Segmenty catch-all pozwalają tworzyć ścieżki, które pasują do dowolnej liczby segmentów. Jest to przydatne w scenariuszach takich jak tworzenie CMS, gdzie struktura URL jest określana przez użytkownika. Segmenty catch-all definiuje się, dodając trzy kropki przed nazwą segmentu (np. `[...slug]`).

Przykład:

app/
  docs/
    [...slug]/
      page.js

Segment `[...slug]` będzie pasował do dowolnej liczby segmentów po `/docs`. Na przykład, będzie pasował do `/docs/getting-started`, `/docs/api/users` i `/docs/advanced/configuration`. Wartość parametru `slug` będzie tablicą zawierającą dopasowane segmenty.

// app/docs/[...slug]/page.js
import React from 'react';

export default function DocsPage({ params }) {
  const { slug } = params;

  return (
    <div>
      <h1>Dokumentacja</h1>
      <p>Slug: {slug ? slug.join('/') : 'Brak sluga'}</p>
    </div>
  );
}

Opcjonalne segmenty catch-all można utworzyć, dodając nazwę segmentu w podwójnych nawiasach kwadratowych `[[...slug]]`. To sprawia, że segment ścieżki jest opcjonalny. Przykład:

app/
  blog/
    [[...slug]]/
      page.js

Ta konfiguracja wyrenderuje komponent page.js zarówno pod adresem `/blog`, jak i `/blog/dowolna/liczba/segmentow`.

10. Ścieżki Równoległe (Parallel Routes)

Ścieżki Równoległe pozwalają na jednoczesne renderowanie jednej lub więcej stron w tym samym layoucie. Jest to szczególnie przydatne w przypadku złożonych layoutów, takich jak pulpity nawigacyjne, gdzie różne sekcje strony mogą być ładowane niezależnie. Ścieżki Równoległe definiuje się za pomocą symbolu `@`, po którym następuje nazwa slotu (np. `@sidebar`, `@main`).

Przykład:

app/
  @sidebar/
    page.js  // Zawartość paska bocznego
  @main/
    page.js  // Zawartość głównej sekcji
  default.js // Wymagane: Definiuje domyślny layout dla ścieżek równoległych

Plik `default.js` jest wymagany przy używaniu ścieżek równoległych. Definiuje on, jak różne sloty są łączone, aby stworzyć ostateczny layout.

// app/default.js
export default function RootLayout({ children: { sidebar, main } }) {
  return (
    <div style={{ display: 'flex' }}>
      <aside style={{ width: '200px', backgroundColor: '#f0f0f0' }}>
        {sidebar}
      </aside>
      <main style={{ flex: 1, padding: '20px' }}>
        {main}
      </main>
    </div>
  );
}

11. Przechwytywanie Ścieżek (Intercepting Routes)

Przechwytywanie Ścieżek pozwala na załadowanie ścieżki z innej części aplikacji w bieżącym layoucie. Jest to przydatne do tworzenia modali, galerii obrazów i innych elementów UI, które powinny pojawiać się nad istniejącą treścią strony. Przechwytywanie Ścieżek definiuje się za pomocą składni `(..)`, która wskazuje, o ile poziomów w górę w drzewie katalogów należy się cofnąć, aby znaleźć przechwyconą ścieżkę.

Przykład:

app/
  (.)photos/
    [id]/
      page.js  // Przechwycona ścieżka
  feed/
    page.js  // Strona, na której wyświetlany jest modal ze zdjęciem

W tym przykładzie, gdy użytkownik kliknie na zdjęcie na stronie `/feed`, ścieżka `app/(.)photos/[id]/page.js` jest przechwytywana i wyświetlana jako modal na stronie `/feed`. Składnia `(.)` informuje Next.js, aby szukał ścieżki `photos/[id]` o jeden poziom wyżej (w katalogu `app`).

Pobieranie Danych z App Routerem

App Router zapewnia wbudowane wsparcie dla pobierania danych za pomocą Komponentów Serwerowych i Komponentów Klienckich. Komponenty Serwerowe są renderowane na serwerze, podczas gdy Komponenty Klienckie są renderowane po stronie klienta. Pozwala to na wybór najlepszego podejścia dla każdego komponentu w zależności od jego wymagań.

Komponenty Serwerowe

Komponenty Serwerowe są domyślne w App Routerze. Pozwalają na bezpośrednie pobieranie danych w komponentach bez potrzeby tworzenia oddzielnych ścieżek API. Może to poprawić wydajność i uprościć kod.

Przykład:

// app/products/page.js
import React from 'react';

export default async function ProductsPage() {
  const products = await fetchProducts();

  return (
    <div>
      <h1>Produkty</h1>
      <ul>
        {products.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}

async function fetchProducts() {
  // Symulacja pobierania danych z bazy danych lub API
  return new Promise((resolve) => {
    setTimeout(() => {
      const products = [
        { id: 1, name: 'Produkt A' },
        { id: 2, name: 'Produkt B' },
        { id: 3, name: 'Produkt C' },
      ];
      resolve(products);
    }, 500);
  });
}

W tym przykładzie funkcja `fetchProducts` jest wywoływana bezpośrednio w komponencie `ProductsPage`. Komponent jest renderowany na serwerze, a dane są pobierane przed wysłaniem HTML do klienta.

Komponenty Klienckie

Komponenty Klienckie są renderowane po stronie klienta i pozwalają na korzystanie z funkcji po stronie klienta, takich jak nasłuchiwanie zdarzeń, stan i API przeglądarki. Aby użyć Komponentu Klienckiego, należy dodać dyrektywę `'use client'` na początku pliku.

Przykład:

// app/counter/page.js
'use client'

import React, { useState } from 'react';

export default function CounterPage() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Licznik</h1>
      <p>Wartość: {count}</p>
      <button onClick={() => setCount(count + 1)}>Zwiększ</button>
    </div>
  );
}

W tym przykładzie komponent `CounterPage` jest Komponentem Klienckim, ponieważ używa hooka `useState`. Dyrektywa `'use client'` informuje Next.js, aby renderował ten komponent po stronie klienta.

Zaawansowane Techniki Routingu

App Router oferuje kilka zaawansowanych technik routingu, które mogą być użyte do tworzenia złożonych i zaawansowanych aplikacji.

1. Handlery Ścieżek (Route Handlers)

Handlery Ścieżek pozwalają tworzyć punkty końcowe API w katalogu `app`. Eliminuje to potrzebę oddzielnego katalogu `pages/api`. Handlery Ścieżek są definiowane w plikach o nazwie `route.js` (lub `route.ts`) i eksportują funkcje, które obsługują różne metody HTTP (np. `GET`, `POST`, `PUT`, `DELETE`).

Przykład:

// app/api/users/route.js
import { NextResponse } from 'next/server'

export async function GET(request) {
  // Symulacja pobierania użytkowników z bazy danych
  const users = [
    { id: 1, name: 'Jan Kowalski' },
    { id: 2, name: 'Anna Nowak' },
  ];

  return NextResponse.json(users);
}

export async function POST(request) {
  const body = await request.json()
  console.log('Otrzymane dane:', body)
  return NextResponse.json({ message: 'Użytkownik utworzony' }, { status: 201 })
}

Ten przykład definiuje handler ścieżki pod adresem `/api/users`, który obsługuje zarówno żądania `GET`, jak i `POST`. Funkcja `GET` zwraca listę użytkowników, a funkcja `POST` tworzy nowego użytkownika.

2. Grupy Ścieżek z Wieloma Layoutami

Możesz łączyć grupy ścieżek z layoutami, aby tworzyć różne layouty dla różnych sekcji aplikacji. Jest to przydatne w scenariuszach, w których chcesz mieć inny nagłówek lub pasek boczny dla różnych części witryny.

Przykład:

app/
  (marketing)/
    layout.js  // Layout marketingowy
    about/
      page.js
    contact/
      page.js
  (admin)/
    layout.js  // Layout panelu administracyjnego
    dashboard/
      page.js

W tym przykładzie strony `about` i `contact` będą używać layoutu `marketing`, podczas gdy strona `dashboard` będzie używać layoutu `admin`.

3. Middleware

Middleware pozwala na uruchomienie kodu przed obsłużeniem żądania przez aplikację. Jest to przydatne do zadań takich jak uwierzytelnianie, autoryzacja, logowanie i przekierowywanie użytkowników na podstawie ich lokalizacji lub urządzenia.

Middleware definiuje się w pliku o nazwie `middleware.js` (lub `middleware.ts`) w głównym katalogu projektu.

Przykład:

// middleware.js
import { NextResponse } from 'next/server'

export function middleware(request) {
  // Sprawdź, czy użytkownik jest uwierzytelniony
  const isAuthenticated = false; // Zastąp swoją logiką uwierzytelniania

  if (!isAuthenticated && request.nextUrl.pathname.startsWith('/admin')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

// Zobacz "Dopasowywanie ścieżek" poniżej, aby dowiedzieć się więcej
export const config = {
  matcher: '/admin/:path*',
}

Ten przykład definiuje middleware, które sprawdza, czy użytkownik jest uwierzytelniony przed zezwoleniem mu na dostęp do dowolnej ścieżki pod `/admin`. Jeśli użytkownik nie jest uwierzytelniony, jest przekierowywany na stronę `/login`.

Dobre Praktyki dla Routingu Opartego na Plikach

Aby w pełni wykorzystać system routingu opartego na plikach w App Routerze, rozważ następujące dobre praktyki:

Przykłady internacjonalizacji z Next.js App Router

Next.js App Router upraszcza internacjonalizację (i18n) poprzez routing oparty na plikach. Oto jak możesz efektywnie wdrożyć i18n:

1. Routing z podścieżkami

Organizuj swoje ścieżki na podstawie języka, używając podścieżek. Na przykład:

app/
  [locale]/
    page.tsx         // Strona główna dla danego języka
    about/
      page.tsx     // Strona "O nas" dla danego języka
// app/[locale]/page.tsx
import { getTranslations } from './dictionaries';

export default async function HomePage({ params: { locale } }) {
  const t = await getTranslations(locale);
  return (<h1>{t.home.title}</h1>);
}

// dictionaries.js
const dictionaries = {
  en: () => import('./dictionaries/en.json').then((module) => module.default),
  es: () => import('./dictionaries/es.json').then((module) => module.default),
};

export const getTranslations = async (locale) => {
  try {
    return dictionaries[locale]() ?? dictionaries.en();
  } catch (error) {
    console.error(`Nie udało się załadować tłumaczeń dla języka ${locale}`, error);
    return dictionaries.en();
  }
};

W tej konfiguracji dynamiczny segment ścieżki `[locale]` obsługuje różne języki (np. `/en`, `/es`). Tłumaczenia są ładowane dynamicznie na podstawie języka.

2. Routing oparty na domenach

Dla bardziej zaawansowanego podejścia możesz używać różnych domen lub subdomen dla każdego języka. Często wymaga to dodatkowej konfiguracji u dostawcy hostingu.

3. Middleware do wykrywania języka

Użyj middleware, aby automatycznie wykrywać preferowany język użytkownika i odpowiednio go przekierowywać.

// middleware.js
import { NextResponse } from 'next/server';
import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

let locales = ['en', 'es', 'fr'];

function getLocale(request) {
  const negotiatorHeaders = {};
  request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
  let languages = new Negotiator({ headers: negotiatorHeaders }).languages();

  try {
      return match(languages, locales, 'en'); // Użyj "en" jako domyślnego języka
  } catch (error) {
      console.error("Błąd podczas dopasowywania języka:", error);
      return 'en'; // Powrót do angielskiego w przypadku niepowodzenia
  }
}

export function middleware(request) {
  const pathname = request.nextUrl.pathname;
  const pathnameIsMissingLocale = locales.every(
    (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
  );

  if (pathnameIsMissingLocale) {
    const locale = getLocale(request);

    return NextResponse.redirect(
      new URL(
        `/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`,
        request.url
      )
    );
  }
}

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

To middleware sprawdza, czy żądana ścieżka ma prefiks językowy. Jeśli nie, wykrywa preferowany język użytkownika za pomocą nagłówka `Accept-Language` i przekierowuje go na odpowiednią ścieżkę z językiem. Biblioteki takie jak `@formatjs/intl-localematcher` i `negotiator` są używane do obsługi negocjacji języka.

Next.js App Router a Globalna Dostępność

Tworzenie globalnie dostępnych aplikacji internetowych wymaga starannego rozważenia zasad dostępności (a11y). Next.js App Router stanowi solidną podstawę do budowania dostępnych doświadczeń, ale kluczowe jest wdrożenie dobrych praktyk, aby zapewnić, że Twoja aplikacja jest użyteczna dla wszystkich, niezależnie od ich zdolności.

Kluczowe Kwestie Dotyczące Dostępności

  1. Semantyczny HTML: Używaj semantycznych elementów HTML (np. `<article>`, `<nav>`, `<aside>`, `<main>`) do strukturyzacji treści. Zapewnia to znaczenie technologiom wspomagającym i pomaga użytkownikom łatwiej nawigować po Twojej witrynie.
  2. Atrybuty ARIA: Używaj atrybutów ARIA (Accessible Rich Internet Applications), aby zwiększyć dostępność niestandardowych komponentów i widżetów. Atrybuty ARIA dostarczają dodatkowych informacji o roli, stanie i właściwościach elementów technologiom wspomagającym.
  3. Nawigacja za pomocą klawiatury: Upewnij się, że wszystkie interaktywne elementy są dostępne za pomocą klawiatury. Użytkownicy powinni móc nawigować po aplikacji za pomocą klawisza `Tab` i wchodzić w interakcje z elementami za pomocą klawiszy `Enter` lub `Spacja`.
  4. Kontrast kolorów: Używaj wystarczającego kontrastu kolorów między tekstem a tłem, aby zapewnić czytelność dla użytkowników z wadami wzroku. Wytyczne dotyczące dostępności treści internetowych (WCAG) zalecają współczynnik kontrastu co najmniej 4.5:1 dla normalnego tekstu i 3:1 dla dużego tekstu.
  5. Tekst alternatywny dla obrazów: Zapewnij opisowy tekst alternatywny dla wszystkich obrazów. Tekst alternatywny stanowi tekstową alternatywę dla obrazów, która może być odczytana przez czytniki ekranu.
  6. Etykiety formularzy: Powiąż etykiety formularzy z odpowiadającymi im polami wejściowymi za pomocą elementu `<label>`. Ułatwia to użytkownikom zrozumienie, jakich informacji oczekuje się w każdym polu.
  7. Testowanie z czytnikiem ekranu: Przetestuj swoją aplikację za pomocą czytnika ekranu, aby upewnić się, że jest dostępna dla użytkowników z wadami wzroku. Popularne czytniki ekranu to NVDA, JAWS i VoiceOver.

Implementacja Dostępności w Next.js App Router

  1. Używaj komponentu Link z Next.js: Używaj komponentu `<Link>` do nawigacji. Zapewnia on wbudowane funkcje dostępności, takie jak wstępne ładowanie (prefetching) i zarządzanie fokusem.
  2. Zarządzanie Fokusem: Podczas nawigacji między stronami lub otwierania modali, upewnij się, że fokus jest prawidłowo zarządzany. Fokus powinien być ustawiony na najbardziej logicznym elemencie na nowej stronie lub w modalu.
  3. Dostępne Komponenty Niestandardowe: Tworząc niestandardowe komponenty, upewnij się, że są one dostępne, stosując się do zasad przedstawionych powyżej. Używaj semantycznego HTML, atrybutów ARIA i nawigacji za pomocą klawiatury, aby Twoje komponenty były użyteczne dla wszystkich.
  4. Linting i Testowanie: Używaj narzędzi do lintingu, takich jak ESLint z wtyczkami dostępności, aby identyfikować potencjalne problemy z dostępnością w Twoim kodzie. Używaj również zautomatyzowanych narzędzi do testowania aplikacji pod kątem naruszeń dostępności.

Podsumowanie

System routingu oparty na plikach w App Routerze Next.js oferuje potężny i intuicyjny sposób na strukturyzowanie i nawigowanie w aplikacjach. Rozumiejąc podstawowe koncepcje i dobre praktyki przedstawione w tym przewodniku, możesz budować solidne, skalowalne i łatwe w utrzymaniu aplikacje Next.js. Eksperymentuj z różnymi funkcjami App Routera i odkryj, jak może on uprościć Twój proces deweloperski i poprawić doświadczenie użytkownika.