Suomi

Ota Next.js App Routerin teho haltuun perusteellisella oppaallamme tiedostopohjaiseen reititykseen. Opi rakentamaan sovelluksesi, luomaan dynaamisia reittejä ja käsittelemään asetteluja.

Next.js App Router: Kattava opas tiedostopohjaiseen reititykseen

Next.js App Router, joka esiteltiin Next.js 13:ssa ja josta on tullut standardi myöhemmissä versioissa, mullistaa tavan, jolla rakennamme ja navigoimme sovelluksissa. Se esittelee tehokkaan ja intuitiivisen tiedostopohjaisen reititysjärjestelmän, joka yksinkertaistaa kehitystä, parantaa suorituskykyä ja kohentaa yleistä kehittäjäkokemusta. Tämä kattava opas syventyy App Routerin tiedostopohjaiseen reititykseen ja antaa sinulle tiedot ja taidot vankkojen ja skaalautuvien Next.js-sovellusten rakentamiseen.

Mitä on tiedostopohjainen reititys?

Tiedostopohjainen reititys on reititysjärjestelmä, jossa sovelluksesi reittien rakenne määräytyy suoraan tiedostojesi ja hakemistojesi organisoinnin perusteella. Next.js App Routerissa reitit määritellään luomalla tiedostoja `app`-hakemistoon. Jokainen kansio edustaa reitin osaa, ja kansioiden sisällä olevat erikoistiedostot määrittävät, miten kyseinen reitin osa käsitellään. Tällä lähestymistavalla on useita etuja:

App Routerin käyttöönotto

Jotta voit käyttää App Routeria, sinun on luotava uusi Next.js-projekti tai siirrettävä olemassa oleva projekti. Varmista, että käytät Next.js-versiota 13 tai uudempaa.

Uuden projektin luominen:

Voit luoda uuden Next.js-projektin App Routerilla käyttämällä seuraavaa komentoa:

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

Olemassa olevan projektin siirtäminen:

Siirtääksesi olemassa olevan projektin sinun on siirrettävä sivusi `pages`-hakemistosta `app`-hakemistoon. Saatat joutua mukauttamaan reitityslogiikkaasi vastaavasti. Next.js tarjoaa siirto-oppaan auttamaan sinua tässä prosessissa.

Tiedostopohjaisen reitityksen peruskäsitteet

App Router esittelee useita erikoistiedostoja ja käytäntöjä, jotka määrittelevät, miten reittejäsi käsitellään:

1. `app`-hakemisto

`app`-hakemisto on sovelluksesi reittien juuri. Kaikkia tämän hakemiston sisällä olevia tiedostoja ja kansioita käytetään reittien generointiin. App Router jättää huomiotta kaiken `app`-hakemiston ulkopuolella olevan (kuten `pages`-hakemiston, jos olet siirtymässä).

2. `page.js`-tiedosto

`page.js`- (tai `page.jsx`, `page.ts`, `page.tsx`) tiedosto on App Routerin perustavanlaatuisin osa. Se määrittelee käyttöliittymäkomponentin, joka renderöidään tietylle reitin osalle. Se on pakollinen tiedosto kaikille reitin osille, joiden haluat olevan suoraan saavutettavissa.

Esimerkki:

Jos sinulla on tällainen tiedostorakenne:

app/
  about/
    page.js

Komponentti, joka exportataan tiedostosta `app/about/page.js`, renderöidään, kun käyttäjä siirtyy osoitteeseen `/about`.

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

export default function AboutPage() {
  return (
    <div>
      <h1>Meistä</h1>
      <p>Lue lisää yrityksestämme.</p>
    </div>
  );
}

3. `layout.js`-tiedosto

`layout.js`- (tai `layout.jsx`, `layout.ts`, `layout.tsx`) tiedosto määrittelee käyttöliittymän, joka jaetaan useiden sivujen kesken reitin osassa. Asettelut ovat hyödyllisiä yhtenäisten ylä- ja alatunnisteiden, sivupalkkien ja muiden elementtien luomiseen, joiden tulisi olla läsnä useilla sivuilla.

Esimerkki:

Oletetaan, että haluat lisätä ylätunnisteen sekä `/about`-sivulle että hypoteettiselle `/about/team`-sivulle. Voit luoda `layout.js`-tiedoston `app/about`-hakemistoon:

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

export default function AboutLayout({ children }) {
  return (
    <div>
      <header>
        <h1>Tietoja yrityksestämme</h1>
      </header>
      <main>{children}</main>
    </div>
  );
}

`children`-props korvataan käyttöliittymällä, jonka renderöi samassa hakemistossa tai missä tahansa sisäkkäisessä hakemistossa oleva `page.js`-tiedosto.

4. `template.js`-tiedosto

`template.js`-tiedosto on samankaltainen kuin `layout.js`, mutta se luo uuden instanssin komponentista jokaiselle lapsireitille. Tämä on hyödyllistä tilanteissa, joissa haluat ylläpitää komponentin tilaa tai estää uudelleenrenderöintejä navigoidessasi lapsireittien välillä. Toisin kuin asettelut, templatet renderöityvät uudelleen navigoinnin yhteydessä. Templatejen käyttö on erinomaista elementtien animointiin navigoinnin aikana.

Esimerkki:

// app/template.js
'use client'

import { useState } from 'react'

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

  return (
    <main>
      <p>Template: {count}</p>
      <button onClick={() => setCount(count + 1)}>Päivitä template</button>
      {children}
    </main>
  )
}

5. `loading.js`-tiedosto

`loading.js`- (tai `loading.jsx`, `loading.ts`, `loading.tsx`) tiedoston avulla voit luoda latausnäkymän, joka näytetään reitin osan latautuessa. Tämä on hyödyllistä paremman käyttäjäkokemuksen tarjoamiseksi datan noudon tai muiden asynkronisten operaatioiden aikana.

Esimerkki:

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

export default function Loading() {
  return <p>Ladataan tietoja...</p>;
}

Kun käyttäjä siirtyy osoitteeseen `/about`, `Loading`-komponentti näytetään, kunnes `page.js`-komponentti on täysin renderöity.

6. `error.js`-tiedosto

`error.js`- (tai `error.jsx`, `error.ts`, `error.tsx`) tiedoston avulla voit luoda mukautetun virhenäkymän, joka näytetään, kun reitin osassa tapahtuu virhe. Tämä on hyödyllistä käyttäjäystävällisemmän virheilmoituksen tarjoamiseksi ja koko sovelluksen kaatumisen estämiseksi.

Esimerkki:

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

import React from 'react';

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Tapahtui virhe!</h2>
      <p>{error.message}</p>
      <button onClick={() => reset()}>Yritä uudelleen</button>
    </div>
  );
}

Jos `/about`-sivun renderöinnin aikana tapahtuu virhe, `Error`-komponentti näytetään. `error`-props sisältää tietoa virheestä, ja `reset`-funktio antaa käyttäjälle mahdollisuuden yrittää ladata sivu uudelleen.

7. Reittiryhmät

Reittiryhmät `(groupName)` mahdollistavat reittien organisoinnin ilman, että se vaikuttaa URL-rakenteeseen. Ne luodaan ympäröimällä kansion nimi sulkeilla. Tämä on erityisen hyödyllistä asettelujen ja jaettujen komponenttien järjestämisessä.

Esimerkki:

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

Tässä esimerkissä `about`- ja `contact`-sivut on ryhmitelty `marketing`-ryhmän alle, ja `products`-sivu on `shop`-ryhmän alla. URL-osoitteet pysyvät vastaavasti `/about`, `/contact` ja `/products`.

8. Dynaamiset reitit

Dynaamiset reitit mahdollistavat reittien luomisen muuttuvilla osilla. Tämä on hyödyllistä sisällön näyttämiseen, joka perustuu tietokannasta tai API:sta noudettuun dataan. Dynaamiset reitin osat määritellään ympäröimällä osan nimi hakasulkeilla (esim. `[id]`).

Esimerkki:

Oletetaan, että haluat luoda reitin yksittäisten blogikirjoitusten näyttämiseen niiden tunnisteen perusteella. Voit luoda tiedostorakenteen näin:

app/
  blog/
    [id]/
      page.js

`[id]`-osa on dynaaminen osa. Komponentti, joka exportataan tiedostosta `app/blog/[id]/page.js`, renderöidään, kun käyttäjä siirtyy URL-osoitteeseen kuten `/blog/123` tai `/blog/456`. `id`-parametrin arvo on saatavilla komponentin `params`-propsissa.

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

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

  // Nouda blogikirjoituksen data annetulla ID:llä
  const post = await fetchBlogPost(id);

  if (!post) {
    return <p>Blogikirjoitusta ei löytynyt.</p>;
  }

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

async function fetchBlogPost(id) {
  // Simuloi datan noutoa tietokannasta tai API:sta
  return new Promise((resolve) => {
    setTimeout(() => {
      const posts = {
        '123': { title: 'Ensimmäinen blogikirjoitukseni', content: 'Tämä on ensimmäisen blogikirjoitukseni sisältö.' },
        '456': { title: 'Toinen blogikirjoitus', content: 'Tässä on lisää jännittävää sisältöä.' },
      };
      resolve(posts[id] || null);
    }, 500);
  });
}

Voit myös käyttää useita dynaamisia osia reitissä. Esimerkiksi sinulla voisi olla reitti kuten `/blog/[category]/[id]`.

9. Kaiken kattavat segmentit (Catch-all)

Kaiken kattavat segmentit (catch-all) mahdollistavat reittien luomisen, jotka vastaavat mitä tahansa määrää segmenttejä. Tämä on hyödyllistä esimerkiksi CMS:n luomisessa, jossa URL-rakenne määräytyy käyttäjän mukaan. Kaiken kattavat segmentit määritellään lisäämällä kolme pistettä ennen segmentin nimeä (esim. `[...slug]`).

Esimerkki:

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

`[...slug]`-segmentti vastaa mitä tahansa määrää segmenttejä `/docs`-polun jälkeen. Se vastaa esimerkiksi polkuja `/docs/getting-started`, `/docs/api/users` ja `/docs/advanced/configuration`. `slug`-parametrin arvo on taulukko, joka sisältää vastaavat segmentit.

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

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

  return (
    <div>
      <h1>Docs</h1>
      <p>Slug: {slug ? slug.join('/') : 'Ei slugia'}</p>
    </div>
  );
}

Valinnaiset kaiken kattavat segmentit voidaan luoda lisäämällä segmentin nimi kaksinkertaisiin hakasulkeisiin `[[...slug]]`. Tämä tekee reitin segmentistä valinnaisen. Esimerkki:

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

Tämä asetus renderöi page.js-komponentin sekä osoitteessa `/blog` että `/blog/any/number/of/segments`.

10. Rinnakkaiset reitit

Rinnakkaiset reitit (Parallel Routes) mahdollistavat yhden tai useamman sivun samanaikaisen renderöinnin samassa asettelussa. Tämä on erityisen hyödyllistä monimutkaisissa asetteluissa, kuten hallintapaneeleissa, joissa sivun eri osiot voidaan ladata itsenäisesti. Rinnakkaiset reitit määritellään käyttämällä `@`-symbolia, jota seuraa slotin nimi (esim. `@sidebar`, `@main`).

Esimerkki:

app/
  @sidebar/
    page.js  // Sivupalkin sisältö
  @main/
    page.js  // Pääosion sisältö
  default.js // Pakollinen: Määrittelee oletusasettelun rinnakkaisille reiteille

`default.js`-tiedosto on pakollinen, kun käytetään rinnakkaisia reittejä. Se määrittelee, miten eri slotit yhdistetään lopullisen asettelun luomiseksi.

// 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. Sieppaavat reitit

Sieppaavat reitit (Intercepting Routes) mahdollistavat reitin lataamisen sovelluksen toisesta osasta nykyisen asettelun sisällä. Tämä on hyödyllistä modaalien, kuvagallerioiden ja muiden käyttöliittymäelementtien luomiseen, joiden tulisi ilmestyä olemassa olevan sivun sisällön päälle. Sieppaavat reitit määritellään käyttämällä `(..)`-syntaksia, joka osoittaa, kuinka monta tasoa hakemistopuussa ylöspäin mennään löytääkseen siepattavan reitin.

Esimerkki:

app/
  (.)photos/
    [id]/
      page.js  // Siepattu reitti
  feed/
    page.js  // Sivu, jolla valokuvamodaali näytetään

Tässä esimerkissä, kun käyttäjä napsauttaa kuvaa `/feed`-sivulla, `app/(.)photos/[id]/page.js`-reitti siepataan ja näytetään modaalina `/feed`-sivun päällä. `(.)`-syntaksi kertoo Next.js:lle, että sen tulee etsiä `photos/[id]`-reittiä yhden tason ylempää (eli `app`-hakemistosta).

Datan nouto App Routerilla

App Router tarjoaa sisäänrakennetun tuen datan noudolle käyttämällä palvelinkomponentteja (Server Components) ja asiakaskomponentteja (Client Components). Palvelinkomponentit renderöidään palvelimella, kun taas asiakaskomponentit renderöidään selaimessa. Tämä antaa sinulle mahdollisuuden valita paras lähestymistapa kullekin komponentille sen vaatimusten perusteella.

Palvelinkomponentit

Palvelinkomponentit ovat oletusarvo App Routerissa. Niiden avulla voit noutaa dataa suoraan komponenteissasi ilman erillisiä API-reittejä. Tämä voi parantaa suorituskykyä ja yksinkertaistaa koodiasi.

Esimerkki:

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

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

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

async function fetchProducts() {
  // Simuloi datan noutoa tietokannasta tai API:sta
  return new Promise((resolve) => {
    setTimeout(() => {
      const products = [
        { id: 1, name: 'Tuote A' },
        { id: 2, name: 'Tuote B' },
        { id: 3, name: 'Tuote C' },
      ];
      resolve(products);
    }, 500);
  });
}

Tässä esimerkissä `fetchProducts`-funktiota kutsutaan suoraan `ProductsPage`-komponentin sisällä. Komponentti renderöidään palvelimella, ja data noudetaan ennen kuin HTML lähetetään selaimelle.

Asiakaskomponentit

Asiakaskomponentit renderöidään selaimessa ja mahdollistavat selainpuolen ominaisuuksien, kuten tapahtumankuuntelijoiden, tilan ja selain-API:en käytön. Jotta voit käyttää asiakaskomponenttia, sinun on lisättävä `'use client'` -direktiivi tiedoston alkuun.

Esimerkki:

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

import React, { useState } from 'react';

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

  return (
    <div>
      <h1>Laskuri</h1>
      <p>Määrä: {count}</p>
      <button onClick={() => setCount(count + 1)}>Kasvata</button>
    </div>
  );
}

Tässä esimerkissä `CounterPage`-komponentti on asiakaskomponentti, koska se käyttää `useState`-hookia. `'use client'` -direktiivi kertoo Next.js:lle, että tämä komponentti tulee renderöidä selaimessa.

Edistyneet reititystekniikat

App Router tarjoaa useita edistyneitä reititystekniikoita, joita voidaan käyttää monimutkaisten ja hienostuneiden sovellusten luomiseen.

1. Reitinkäsittelijät (Route Handlers)

Reitinkäsittelijät (Route Handlers) mahdollistavat API-päätepisteiden luomisen `app`-hakemiston sisällä. Tämä poistaa tarpeen erilliselle `pages/api`-hakemistolle. Reitinkäsittelijät määritellään tiedostoissa nimeltä `route.js` (tai `route.ts`), ja ne vievät funktioita, jotka käsittelevät eri HTTP-metodeja (esim. `GET`, `POST`, `PUT`, `DELETE`).

Esimerkki:

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

export async function GET(request) {
  // Simuloi käyttäjien noutoa tietokannasta
  const users = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Doe' },
  ];

  return NextResponse.json(users);
}

export async function POST(request) {
  const body = await request.json()
  console.log('Vastaanotettu data:', body)
  return NextResponse.json({ message: 'Käyttäjä luotu' }, { status: 201 })
}

Tämä esimerkki määrittelee reitinkäsittelijän osoitteessa `/api/users`, joka käsittelee sekä `GET`- että `POST`-pyyntöjä. `GET`-funktio palauttaa listan käyttäjistä, ja `POST`-funktio luo uuden käyttäjän.

2. Reittiryhmät useilla asetteluilla

Voit yhdistää reittiryhmiä ja asetteluja luodaksesi erilaisia asetteluja sovelluksesi eri osioille. Tämä on hyödyllistä tilanteissa, joissa haluat erilaisen ylätunnisteen tai sivupalkin sivustosi eri osiin.

Esimerkki:

app/
  (marketing)/
    layout.js  // Markkinointiasettelu
    about/
      page.js
    contact/
      page.js
  (admin)/
    layout.js  // Ylläpitoasettelu
    dashboard/
      page.js

Tässä esimerkissä `about`- ja `contact`-sivut käyttävät `marketing`-asettelua, kun taas `dashboard`-sivu käyttää `admin`-asettelua.

3. Middleware

Middlewaren avulla voit suorittaa koodia ennen kuin sovelluksesi käsittelee pyynnön. Tämä on hyödyllistä tehtävissä kuten todennus, valtuutus, lokitus ja käyttäjien uudelleenohjaus heidän sijaintinsa tai laitteensa perusteella.

Middleware määritellään tiedostossa nimeltä `middleware.js` (tai `middleware.ts`) projektisi juuressa.

Esimerkki:

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

export function middleware(request) {
  // Tarkista, onko käyttäjä todennettu
  const isAuthenticated = false; // Korvaa omalla todennuslogiikallasi

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

  return NextResponse.next();
}

// Katso "Matching Paths" alempaa lisätietoja varten
export const config = {
  matcher: '/admin/:path*',
}

Tämä esimerkki määrittelee middlewaren, joka tarkistaa, onko käyttäjä todennettu, ennen kuin sallii pääsyn mihin tahansa `/admin`-polun alla olevaan reittiin. Jos käyttäjä ei ole todennettu, hänet ohjataan `/login`-sivulle.

Tiedostopohjaisen reitityksen parhaat käytännöt

Saadaksesi kaiken irti App Routerin tiedostopohjaisesta reititysjärjestelmästä, harkitse seuraavia parhaita käytäntöjä:

Esimerkkejä kansainvälistämisestä Next.js App Routerilla

Next.js App Router yksinkertaistaa kansainvälistämistä (i18n) tiedostopohjaisen reitityksen avulla. Näin voit toteuttaa i18n:n tehokkaasti:

1. Alipolkureititys

Järjestä reitit kieliversion (locale) mukaan käyttämällä alipolkuja. Esimerkiksi:

app/
  [locale]/
    page.tsx         // Kotisivu kieliversiolle
    about/
      page.tsx     // Tietoja-sivu kieliversiolle
// 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(`Kieliversion ${locale} käännösten lataaminen epäonnistui`, error);
    return dictionaries.en();
  }
};

Tässä asetelmassa `[locale]` dynaaminen reitin osa käsittelee eri kieliversioita (esim. `/en`, `/es`). Käännökset ladataan dynaamisesti kieliversion perusteella.

2. Verkkotunnusreititys

Edistyneempää lähestymistapaa varten voit käyttää eri verkkotunnuksia tai aliverkkotunnuksia kullekin kieliversiolle. Tämä vaatii usein lisäkonfiguraatiota hosting-palveluntarjoajasi kanssa.

3. Middleware kieliversion tunnistamiseen

Käytä middlewarea tunnistaaksesi automaattisesti käyttäjän suosiman kieliversion ja ohjataksesi hänet sen mukaisesti.

// 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'); // Käytä "en" oletuskieliversiona
  } catch (error) {
      console.error("Virhe kieliversion yhdistämisessä:", error);
      return 'en'; // Palataan englantiin, jos yhdistäminen epäonnistuu
  }
}

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).*)',
  ],
};

Tämä middleware tarkistaa, onko pyydetyssä polussa kieliversion etuliitettä. Jos ei ole, se tunnistaa käyttäjän suosiman kieliversion `Accept-Language`-otsakkeesta ja ohjaa hänet sopivaan kieliversiokohtaiseen polkuun. Kirjastoja, kuten `@formatjs/intl-localematcher` ja `negotiator`, käytetään kieliversioneuvottelun hoitamiseen.

Next.js App Router ja globaali saavutettavuus

Globaalisti saavutettavien verkkosovellusten luominen vaatii saavutettavuuden (a11y) periaatteiden huolellista harkintaa. Next.js App Router tarjoaa vankan perustan saavutettavien kokemusten rakentamiselle, mutta on olennaista toteuttaa parhaita käytäntöjä varmistaakseen, että sovellus on kaikkien käytettävissä heidän kyvyistään riippumatta.

Keskeiset saavutettavuusnäkökohdat

  1. Semanttinen HTML: Käytä semanttisia HTML-elementtejä (esim. `<article>`, `<nav>`, `<aside>`, `<main>`) sisällön jäsentämiseen. Tämä antaa merkityksen avustaville teknologioille ja auttaa käyttäjiä navigoimaan sivustollasi helpommin.
  2. ARIA-attribuutit: Käytä ARIA (Accessible Rich Internet Applications) -attribuutteja parantamaan mukautettujen komponenttien ja widgettien saavutettavuutta. ARIA-attribuutit tarjoavat lisätietoa elementtien roolista, tilasta ja ominaisuuksista avustaville teknologioille.
  3. Näppäimistöllä navigointi: Varmista, että kaikki interaktiiviset elementit ovat saavutettavissa näppäimistöllä. Käyttäjien tulee pystyä navigoimaan sovelluksessasi `Tab`-näppäimellä ja olemaan vuorovaikutuksessa elementtien kanssa `Enter`- tai `Välilyönti`-näppäimellä.
  4. Värikontrasti: Käytä riittävää värikontrastia tekstin ja taustan välillä varmistaaksesi luettavuuden näkövammaisille käyttäjille. Verkkosisällön saavutettavuusohjeet (WCAG) suosittelevat vähintään 4.5:1 kontrastisuhdetta normaalille tekstille ja 3:1 suurelle tekstille.
  5. Kuvan alt-teksti: Tarjoa kuvaileva alt-teksti kaikille kuville. Alt-teksti tarjoaa tekstivaihtoehdon kuville, jonka ruudunlukijat voivat lukea.
  6. Lomakkeen selitteet: Yhdistä lomakkeen selitteet vastaaviin syöttökenttiin käyttämällä `<label>`-elementtiä. Tämä tekee käyttäjille selväksi, mitä tietoja kussakin kentässä odotetaan.
  7. Ruudunlukijatestaus: Testaa sovellustasi ruudunlukijalla varmistaaksesi, että se on saavutettavissa näkövammaisille käyttäjille. Suosittuja ruudunlukijoita ovat NVDA, JAWS ja VoiceOver.

Saavutettavuuden toteuttaminen Next.js App Routerissa

  1. Käytä Next.js Link-komponenttia: Käytä `<Link>`-komponenttia navigointiin. Se tarjoaa sisäänrakennettuja saavutettavuusominaisuuksia, kuten esilatauksen ja fokuksen hallinnan.
  2. Fokuksen hallinta: Kun navigoit sivujen välillä tai avaat modaaleja, varmista, että fokus hallitaan oikein. Fokus tulisi asettaa uuden sivun tai modaalin loogisimpaan elementtiin.
  3. Saavutettavat mukautetut komponentit: Kun luot mukautettuja komponentteja, varmista, että ne ovat saavutettavia noudattamalla yllä hahmoteltuja periaatteita. Käytä semanttista HTML:ää, ARIA-attribuutteja ja näppäimistöllä navigointia tehd_äksesi komponenteistasi kaikkien käytettävissä olevia.
  4. Linttaus ja testaus: Käytä linttaustyökaluja, kuten ESLintia saavutettavuuslisäosien kanssa, tunnistaaksesi mahdolliset saavutettavuusongelmat koodissasi. Käytä myös automaattisia testaustyökaluja testataksesi sovelluksesi saavutettavuusrikkomusten varalta.

Yhteenveto

Next.js App Routerin tiedostopohjainen reititysjärjestelmä tarjoaa tehokkaan ja intuitiivisen tavan jäsentää ja navigoida sovelluksissasi. Ymmärtämällä tässä oppaassa esitetyt peruskäsitteet ja parhaat käytännöt voit rakentaa vakaita, skaalautuvia ja ylläpidettäviä Next.js-sovelluksia. Kokeile App Routerin eri ominaisuuksia ja löydä, miten se voi yksinkertaistaa kehitystyönkulkuasi ja parantaa käyttäjäkokemusta.