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

Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen

Liittäkää hakuihin välimuistitunnisteet ja mitätöikää täsmälleen muutosten vaikutuksen alaiset tiedot.

Oppitunti 3/413 vaihetta

Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen on ilmainen Next.js 15 -fullstack-kehitys (App Router + Server Actions)-oppitunti CoddyKitissä. Tämä on oppitunti 3/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.

Tunnisteisiin perustuvan mitätöinnin syy

Next.js 15:ssä Data Cache säilyttää fetch-tulokset pyyntöjen ja käyttöönottokertojen välillä. Haasteena on mitätöidä muutoksen jälkeen täsmälleen oikeat merkinnät.

  • Aikaperusteinen päivitys (revalidate: 60) on karkea ja kelloon sidottu.
  • Polkukohtainen päivitys (revalidatePath) tyhjentää kokonaisia reittisegmenttejä.
  • Tunnisteisiin perustuvassa päivityksessä yksittäiset haut voidaan merkitä tunnisteilla ja mitätöidä vain ne riippumatta siitä, millä sivulla ne näytettiin.

Tunnisteet mahdollistavat tarkan ja kohdennetun välimuistin tyhjennyksen: kun päivitätte yhden tuotteen, mitätöitte vain kyseisen tuotteen lukevat haut.

Tunnisteen liittäminen hakuun

Liitätte tunnisteet laajennetun fetch-funktion next.tags-asetuksella. Kukin tunniste on itse valitsemanne tavallinen merkkijono.

Tässä tuoteluettelon haku merkitään kahdella tunnisteella: yleisellä products-tunnisteella ja tarkalla product-42-tunnisteella.

  • Yleinen tunniste mitätöi koko kokoelman.
  • Tarkka tunniste mitätöi yhden kohteen.
async function getProduct(id: string) {
  const res = await fetch(`https://api.shop.com/products/${id}`, {
    next: { tags: ['products', `product-${id}`] },
  });
  if (!res.ok) throw new Error('Failed to load product');
  return res.json();
}

Mitätöinti revalidateTag-toiminnolla

Soittakaa muutoksen jälkeen revalidateTag(tag)-toimintoa next/cache-moduulista. Jokainen kyseistä tunnistetta sisältävä välimuistissa oleva fetch merkitään vanhentuneeksi, ja seuraava pyyntö hakee tuoreen datan.

Tämä suoritetaan Server Actionissa tai Route Handlerissa eli palvelimen kontekstissa, jossa muutokset tehdään.

  • revalidateTag ei palauta uudelleenhakua varten odotettavaa promisea, vaan merkitsee merkinnät ainoastaan vanhentuneiksi.
  • Useita tunnisteita? Kutsukaa toimintoa kerran kutakin tunnistetta kohden.
'use server';
import { revalidateTag } from 'next/cache';

export async function updateProduct(id: string, data: FormData) {
  await fetch(`https://api.shop.com/products/${id}`, {
    method: 'PATCH',
    body: JSON.stringify({ name: data.get('name') }),
  });
  // Bust only this product's cached reads
  revalidateTag(`product-${id}`);
}

Yleiset ja tarkat tunnisteet

Suunnitelkaa pieni tunnistehierarkia, jotta voitte valita sopivan vaikutusalueen:

  • products — mitätöi koko tuoteluettelon, esimerkiksi massatuonnin jälkeen.
  • product-42 — mitätöi yhden kohteen, esimerkiksi muokkauksen jälkeen.
  • product-42-reviews — mitätöi siihen liittyvän osan koskematta itse tuotteeseen.

Nyrkkisääntö: merkitkää jokainen haku sekä kokoelman että entiteetin tunnisteella. Tällöin muutokset voidaan kohdistaa pienimpään muutoksen kattavaan tunnisteeseen.

Lukujen merkitseminen tunnisteilla eri sivuilla

Tunniste on globaali Data Cachessa, eikä se ole sidottu reittiin. Jos sekä etusivu että tietosivu hakevat product-42-tuotteen samalla tunnisteella, yksi revalidateTag('product-42') tyhjentää molempien välimuistin.

Tämä on keskeinen etu verrattuna revalidatePath-toimintoon: teidän ei tarvitse tietää, mitkä sivut käyttivät dataa.

// app/page.tsx (home) and app/products/[id]/page.tsx both call this
export async function getProductSummary(id: string) {
  const res = await fetch(`https://api.shop.com/products/${id}`, {
    next: { tags: [`product-${id}`] },
  });
  return res.json();
}

unstable_cache muulle kuin fetch-datalle

Kaikki data ei tule fetch-funktion kautta — suorat tietokantakyselyt (Prisma, Drizzle) ohittavat Data Cachen. Käärikää ne unstable_cache-funktion avulla, jotta saatte käyttöön tunnistetuen.

Kolmas argumentti hyväksyy tags- ja revalidate-asetukset. Sama revalidateTag-kutsu mitätöi myös nämä merkinnät.

import { unstable_cache } from 'next/cache';
import { db } from '@/lib/db';

export const getCachedUser = unstable_cache(
  async (id: string) => db.user.findUnique({ where: { id } }),
  ['user-by-id'],
  { tags: ['users'], revalidate: 3600 },
);

Dynaamiset tunnisteet unstable_cache-funktiossa

Välimuistin avainosien eli toisen argumentin on oltava riittävän staattisia funktion tunnistamista varten, mutta usein tarvitsette entiteettikohtaisen tunnisteen. Muodostakaa tunniste argumentista ja välittäkää se asetuksissa.

Palauttakaa funktio, jotta jokainen kutsu saa oikean entiteetin tunnisteen ja mahdollistaa tarkan revalidateTag('user-7')-mitätöinnin.

import { unstable_cache } from 'next/cache';
import { db } from '@/lib/db';

export function getCachedUser(id: string) {
  return unstable_cache(
    async () => db.user.findUnique({ where: { id } }),
    ['user', id],
    { tags: [`user-${id}`, 'users'] },
  )();
}

Tunnistenimien turvallinen muodostaminen

Epäjohdonmukaiset tunnistemerkkijonot aiheuttavat hiljaisia virheitä — väärä tunniste ei mitätöi mitään. Keskittäkää tunnisteiden muodostaminen puhtaisiin apufunktioihin, jotta luku- ja kirjoitusoperaatiot käyttävät aina samoja tunnisteita.

Tämä on itsenäistä ja idiomaattista TypeScriptiä: apufunktiot tuottavat täsmälleen samat merkkijonot, joita käytetään sekä next.tags-asetuksessa että revalidateTag-kutsussa.

const tags = {
  products: () => 'products',
  product: (id: string) => `product-${id}`,
  productReviews: (id: string) => `product-${id}-reviews`,
};

console.log(tags.products());
console.log(tags.product('42'));
console.log(tags.productReviews('42'));

Useiden tunnisteiden atominen mitätöinti

Yksi muutos vaikuttaa usein useisiin välimuistissa oleviin osiin. Tuotteen päivittämisen jälkeen saatatte joutua mitätöimään kohteen, kokoelman luettelon ja hakuindeksin.

Kutsukaa revalidateTag-toimintoa kullekin tunnisteelle. Kaikki astuvat voimaan yhdessä ennen kuin toiminnon vastaus palautetaan asiakkaalle.

  • Järjestyksellä ei ole väliä — kaikki merkitään vanhentuneiksi.
  • Pidättehän joukon mahdollisimman pienenä, jotta muualla ei tehdä tarpeettomia uudelleenhakuja.
'use server';
import { revalidateTag } from 'next/cache';

export async function publishProduct(id: string) {
  await fetch(`https://api.shop.com/products/${id}/publish`, { method: 'POST' });
  revalidateTag(`product-${id}`);
  revalidateTag('products');
  revalidateTag('search-index');
}

Tunniste vai polku: valinta

revalidateTag ja revalidatePath ovat olemassa eri tarkoituksiin:

  • Käyttäkää tunnisteita, kun sama data näkyy monilla reiteillä tai haluatte mitätöidä vain datan ettekä asettelun hahmonteleman reitin renderöidyn välimuistin oletuksia.
  • Käyttäkää polkua, kun koko reitin tulos muuttui ettekä seuraa sen tunnisteita.

Niitä voidaan käyttää yhdessä: Server Action voi kutsua molempia. Suosikaa tunnisteita dataan ja polkuja koko sivun rakenteellisiin muutoksiin.

Kokonaisuus Server Actionissa

Tässä on koko työnkulku: lomake lähettää tiedot Server Actionille, toiminto muuttaa taustajärjestelmää ja mitätöi sitten tarkat tunnisteet. Seuraavalla kerralla mikä tahansa kyseisiä tunnisteita lukeva sivu saa automaattisesti tuoreet tiedot.

Huomaattehan, että mitätöimme sekä entiteetin että kokoelman tunnisteen, koska muutos vaikuttaa myös luetteloon.

'use server';
import { revalidateTag } from 'next/cache';
import { redirect } from 'next/navigation';

export async function editProduct(id: string, formData: FormData) {
  await fetch(`https://api.shop.com/products/${id}`, {
    method: 'PATCH',
    body: JSON.stringify({ name: formData.get('name') }),
    headers: { 'Content-Type': 'application/json' },
  });
  revalidateTag(`product-${id}`);
  revalidateTag('products');
  redirect(`/products/${id}`);
}

Pikatarkistus

Tuotteen tietojen haku on merkitty tunnisteilla ['products', 'product-42'], ja sama haku näytetään myös etusivun luettelossa. Muokkaatte vain tuotteen 42 nimeä. Mikä on tarkin tapa päivittää molemmat näkymät ilman muiden tuotteiden liiallista mitätöintiä?

Kertaus

Opitte tarkan, tunnisteisiin perustuvan välimuistin tyhjennyksen Next.js 15:ssä:

  • Liittäkää tunnisteet fetch-kutsuun asetuksella next: { tags: [...] } ja muuhun kuin fetch-dataan unstable_cache-funktion tags-asetuksella.
  • Käyttäkää kokoelman tunnistetta ja entiteettikohtaista tunnistetta, jotta muutokset voidaan kohdistaa pienimmälle vaikutusalueelle.
  • Kutsukaa revalidateTag(tag)-toimintoa Server Actionien tai Route Handlerien sisällä, kerran kutakin tunnistetta kohden ja atomisesti.
  • Tunnisteet ovat globaaleja: yksi kutsu päivittää datan jokaisella sitä lukeneella reitillä, toisin kuin revalidatePath.
  • Keskittäkää tunnistemerkkijonot apufunktioihin, jotta luku- ja kirjoitusoperaatiot eivät koskaan eriydy toisistaan.
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 ”Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen” 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 “Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen”. 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 ”Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen”?

Liittäkää hakuihin välimuistitunnisteet ja mitätöikää täsmälleen muutosten vaikutuksen alaiset tiedot. 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 3/4.

Kuinka kauan ”Tunnistepohjainen mitätöinti tarkkaan välimuistin tyhjennykseen”-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)