Next.js 15 -fullstack-kehitys (App Router + Server Actions) · Oppitunti

Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat

Yhdistäkää revalidate-välit revalidatePath- ja revalidateTag-kutsuihin hallitaksenne tietojen tuoreutta tarkasti.

Oppitunti 2/413 vaihetta

Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat on ilmainen Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Next.js 15 -fullstack-kehitys (App Router + Server Actions)-kurssilla on yhteensä 4 oppituntia.

Tuoreuden kaksi ulottuvuutta

App Routerissa välimuistissa oleva reitti tai fetch-kutsu voidaan päivittää kahdella toisistaan riippumattomalla tavalla:

  • Aikaperusteinen päivitys: data vanhentuu kiinteän sekuntimäärän jälkeen (revalidate).
  • Tarvittaessa tehtävä päivitys: mitätöitte välimuistin nimenomaisesti, kun jokin todella muuttuu, käyttämällä revalidatePath- tai revalidateTag-funktiota.

Todellisissa sovelluksissa käytetään molempia. Aikaperusteinen päivitys toimii turvaverkkona, jotta sisältö ei vanhene liikaa; tarvittaessa tehtävä päivitys tuo välittömät muutokset silloin, kun hallitsette kirjoitusta. Tässä oppitunnissa opitte yhdistämään ne täsmällistä tuoreuden hallintaa varten.

Aikaperusteinen päivitys segmentin asetuksella

Yksinkertaisin aikaperusteinen strategia on reittisegmentin revalidate-vientimääritys. Next.js tarjoaa välimuistissa olevan renderöinnin, kunnes aikaväli on kulunut, ja luo sen jälkeen uuden version taustalla (stale-while-revalidate).

Arvo 3600 tarkoittaa ”enintään tunnin vanha”. Arvo 0 poistaa segmentin välimuistista; false tallentaa sen välimuistiin määräämättömäksi ajaksi.

// app/products/page.tsx
// Revalidate this Server Component page at most once per hour
export const revalidate = 3600;

export default async function ProductsPage() {
  const res = await fetch('https://api.example.com/products');
  const products: { id: string; name: string }[] = await res.json();

  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name}</li>
      ))}
    </ul>
  );
}

Fetch-kohtainen revalidate

Koko segmenttiä ei tarvitse päivittää kerralla. Jokaisella fetch-kutsulla voi olla oma aikaperusteinen käytäntönsä next.revalidate-option kautta.

Näin samalla sivulla voidaan yhdistää nopeasti muuttuva ja hitaasti muuttuva resurssi. Segmentin todelliseksi revalidate-arvoksi tulee fetch-kutsujen ja segmentin asetusten pienin arvo.

// app/dashboard/page.tsx
export default async function Dashboard() {
  // Prices change often: refresh every 60s
  const prices = await fetch('https://api.example.com/prices', {
    next: { revalidate: 60 },
  }).then((r) => r.json());

  // Categories rarely change: refresh once a day
  const categories = await fetch('https://api.example.com/categories', {
    next: { revalidate: 86400 },
  }).then((r) => r.json());

  return <Report prices={prices} categories={categories} />;
}

Miksi aika yksin ei riitä

Aikaperusteisella päivityksellä on rakenteellinen heikkous: se ei tiedä, onko mikään todella muuttunut. Kun revalidate = 3600:

  • Tuotetta muokkaava käyttäjä näkee vanhan version vielä enintään tunnin ajan.
  • Jos mikään ei muuttunut, renderöinti luodaan silti uudelleen, mikä kuluttaa laskentaresursseja turhaan.

Ratkaisu on yhdistää pitkä aikaväli (turvaverkko) omien kirjoitustoimintojen käynnistämään tarvittaessa tehtävään mitätöintiin. Aika estää dataa vanhenemasta todella vanhaksi, ja tarvittaessa tehtävä päivitys saa tarkoitukselliset muutokset tuntumaan välittömiltä.

revalidatePath: mitätöinti reitin perusteella

revalidatePath tyhjentää tietyn reitin välimuistin, joten seuraava pyyntö muodostaa sen uudelleen. Kutsukaa sitä Server Actionista tai Route Handlerista kirjoitusoperaation jälkeen.

  • Välittäkää tarkka polku, kuten '/products'.
  • Välittäkää dynaaminen malli ja 'page', kun haluatte kohdistaa toiminnon yhteen dynaamiseen reittiin: revalidatePath('/products/[id]', 'page').
  • Välittäkää 'layout', kun haluatte mitätöidä asettelun ja kaiken sen alle sisäkkäisesti sijoittuvan sisällön.
'use server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';

export async function updateProduct(id: string, name: string) {
  await db.product.update({ where: { id }, data: { name } });

  // Refresh the list and this product's detail page
  revalidatePath('/products');
  revalidatePath('/products/[id]', 'page');
}

revalidateTag: Mitätöinti datan perusteella

revalidatePath keskittyy reitteihin, mutta sama data voi näkyä monilla reiteillä. revalidateTag keskittyy dataan: merkitsette haut tunnisteilla ja mitätöitte sitten kaikki välimuistimerkinnät, joilla on sama tunniste, riippumatta siitä, millä reitillä ne näytetään.

Lisätkää tunnisteet ensin haun yhteydessä:

// lib/products.ts
export async function getProducts() {
  const res = await fetch('https://api.example.com/products', {
    next: { tags: ['products'], revalidate: 3600 },
  });
  return res.json();
}

export async function getProduct(id: string) {
  const res = await fetch(`https://api.example.com/products/${id}`, {
    next: { tags: ['products', `product:${id}`] },
  });
  return res.json();
}

revalidateTag-kutsun käynnistäminen kirjoitusoperaatiosta

Kun tunnisteet ovat käytössä, yksi kutsu mitätöi kaiken kyseisellä tunnisteella merkityn. Yleinen tunniste, kuten 'products', päivittää luettelot, ruudukot ja tietosivut kerralla; tarkempi tunniste, kuten product:42, päivittää vain kyseisen kohteen välimuistimerkinnät.

Käyttäkää molempia: mitätöikää muokatun rivin tarkka tunniste sekä kokoelman tunniste kaikille koontinäkymille.

'use server';
import { revalidateTag } from 'next/cache';
import { db } from '@/lib/db';

export async function editProduct(id: string, name: string) {
  await db.product.update({ where: { id }, data: { name } });

  revalidateTag(`product:${id}`); // this item's detail entries
  revalidateTag('products');      // any list/grid that shows it
}

Polku vai tunniste: valinta

Näin päätätte, kumpaa pyynnöstä käytettävää työkalua käytätte:

  • Käyttäkää revalidatePath-toimintoa, kun tiedätte tarkasti, mitkä reitit muuttuivat ja vastaavuus on yksinkertainen, esimerkiksi CMS-sivun slug-arvon tapauksessa.
  • Käyttäkää revalidateTag-toimintoa, kun yksi data-alkio näkyy monilla reiteillä tai reittejä on vaikea luetella, kuten hakusivuilla, aiheeseen liittyvien kohteiden komponenteissa tai sivustokartoissa.

Ne eivät sulje toisiaan pois. Yleinen toimintamalli on merkitä taustalla olevat haut tunnisteilla, jotta data voi näkyä monissa paikoissa, ja kutsua lisäksi revalidatePath-toimintoa paljon liikennöidylle aloitussivulle, jonka haluatte päivittää heti.

Ajan ja pyynnöstä tehtävän päivityksen yhdistäminen

Tuotantoympäristön toimintamalli koostuu kerroksista:

  • Asettakaa tunnisteilla merkityille hauille riittävän pitkä aikaväli (revalidate: 3600) varmistukseksi muutoksille, joita ette hallitse.
  • Kutsukaa revalidateTag-toimintoa jokaisessa Server Actionissa, joka kirjoittaa kyseistä dataa, jotta hallitsemanne muutokset päivittyvät heti.

Tuloksena muokkaukset näkyvät heti, mutta ulkopuolinen vanhentunut data ei voi olla yli tuntia vanhaa. Tämä on paras tasapaino "tarkan ajantasaisuuden hallinnan" kannalta.

'use server';
import { revalidateTag } from 'next/cache';
import { db } from '@/lib/db';

// Fetch elsewhere uses: next: { tags: ['orders'], revalidate: 3600 }
export async function createOrder(input: { sku: string; qty: number }) {
  const order = await db.order.create({ data: input });
  revalidateTag('orders'); // instant; time interval is the backstop
  return order.id;
}

Pyynnöstä tehtävä päivitys Webhook Route Handlerin kautta

Kun data muuttuu sovelluksen ulkopuolella, esimerkiksi headless-CMS-julkaisun tai upstream-synkronoinnin seurauksena, käynnistäkää päivitys Route Handlerista, jota ulkoinen järjestelmä kutsuu. Suojatkaa se salaisuudella, jotta sitä ei voida käyttää väärin.

// app/api/revalidate/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { revalidateTag } from 'next/cache';

export async function POST(req: NextRequest) {
  const secret = req.nextUrl.searchParams.get('secret');
  if (secret !== process.env.REVALIDATE_SECRET) {
    return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
  }

  const { tag } = await req.json();
  revalidateTag(tag);
  return NextResponse.json({ revalidated: true, now: Date.now() });
}

Muistettavat erityistapaukset

Seuraavat toimintatavat aiheuttavat usein sekaannusta:

  • revalidatePath/revalidateTag merkitsevät välimuistin vain vanhentuneeksi; uudelleenluonti tapahtuu seuraavan pyynnön yhteydessä, ei heti toimintonne aikana.
  • Niitä on suoritettava palvelimella, Server Actionissa tai Route Handlerissa, ei koskaan Client Componentissa.
  • fetch, jossa on cache: 'no-store' tai revalidate: 0, ei koskaan käytä välimuistia, joten siihen liitetyillä tunnisteilla ei ole mitään mitätöitävää.
  • Tunnisteet liitetään fetch-datan välimuistiin. Valitkaa tunnisteille pysyvät ja ennakoitavat nimet, jotta kirjoittajat ja lukijat käyttävät samoja nimiä.

Pikatarkistus

Valitkaa alla kuvattuun tilanteeseen täsmällisin toimintamalli.

Kertaus

Yhdistitte kaksi ajantasaisuuden ulottuvuutta tarkkaa hallintaa varten:

  • Aikaperusteinen: segmentin export const revalidate tai haun next: { revalidate } toimii varmistuksena hallitsemattomia muutoksia vastaan.
  • Reittikohtainen pyynnöstä tehtävä päivitys: revalidatePath, kun tiedätte tarkasti, mikä reitti muuttui.
  • Datakohtainen pyynnöstä tehtävä päivitys: revalidateTag, kun yksi resurssi näkyy monilla reiteillä.

Tuotantoympäristön toimintamalli on riittävän pitkä aikaväli tunnisteilla merkityille hauille sekä revalidateTag jokaisessa dataa kirjoittavassa Server Actionissa. Ulkoisia muutoksia varten käytetään lisäksi salaisuudella suojattua webhookia. Muokkaukset näkyvät heti ja vanhentuneisuus pysyy rajattuna.

Aloita maksutta

Opi TypeScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
22
Oppitunnit
88

Usein kysytyt kysymykset

Onko oppitunti ”Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppimispolun 3 oppituntia, myös oppitunnin “Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Next.js 15 -fullstack-kehitys (App Router + Server Actions)-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat”?

Yhdistäkää revalidate-välit revalidatePath- ja revalidateTag-kutsuihin hallitaksenne tietojen tuoreutta tarkasti. Harjoittelet Next.js 15 -fullstack-kehitys (App Router + Server Actions)-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Next.js 15 -fullstack-kehitys (App Router + Server Actions)-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppitunnilla?

Kyllä. Jokainen Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Neljä välimuistia: pyyntö, data, koko reitti ja reititin
  2. Aikaperusteiset ja tarpeen mukaan tehtävät uudelleenvalidointistrategiat
  3. Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen
  4. Välimuistin ohittaminen: dynaaminen renderöinti ja no-store
← Takaisin: Next.js 15 -fullstack-kehitys (App Router + Server Actions)