spinny:~/writing $ less nextjs-16-cache-components.md
12Για χρόνια μια από τις πιο ενοχλητικές ερωτήσεις στο Next.js ήταν: "Είναι αυτή η σελίδα στατική ή δυναμική;". Φαίνεται σαν μια απλή ερώτηση, μέχρι να προσθέσετε μια κλήση στο `cookies()`, ένα `fetch` με διαφορετικές επιλογές, ένα πρόγραμμα-πελάτη βάσης δεδομένων, ένα CMS, ένα καλάθι αγορών ή ένα κομμάτι προσαρμοσμένου περιεχομένου.34Το Next.js 16 είναι ενδιαφέρον γιατί προσπαθεί να κάνει αυτή τη συζήτηση λιγότερο μυστηριώδη. Δεν εξαλείφει την πολυπλοκότητα, αλλά αλλάζει το νοητικό μοντέλο: οι διαδρομές είναι δυναμικές από προεπιλογή, η κρυφή μνήμη δηλώνει όπου χρειάζεται και το `Suspense` γίνεται ο φυσικός τρόπος για να συνθέσετε γρήγορα κελύφη με μέρη που παραμένουν φρέσκα.56Το χαρακτηριστικό που πρέπει να κατανοήσετε είναι τα στοιχεία της προσωρινής μνήμης. Το Stable Turbopack, το React Compiler, το `proxy.ts` και τα νέα API ακύρωσης είναι σημαντικά, αλλά περιστρέφονται γύρω από το ίδιο πρόβλημα: δημιουργία γρήγορων εφαρμογών χωρίς να χρειάζεται να μαντέψετε τι αποφάσισε το πλαίσιο στα παρασκήνια.78## Γιατί αυτό το πράγμα έχει σημασία910Σε μια πραγματική εφαρμογή δεν έχετε απλώς "στατικές σελίδες" και "δυναμικές σελίδες". Έχετε διαφορετικά κομμάτια με διαφορετικές ανάγκες.1112Το φύλλο προϊόντος μπορεί να αλλάζει μερικές φορές την ημέρα. Η τιμή μπορεί να αλλάζει πιο συχνά. Η διαθεσιμότητα πρέπει να είναι σχεδόν ζωντανή. Το όνομα χρήστη είναι προσωπικό. Οι κριτικές μπορούν να μεταδοθούν σε ροή. Η πλαϊνή μπάρα μπορεί να είναι σταθερή. Το καλάθι όχι.1314Εάν αντιμετωπίζετε τα πάντα ως μια μονάδα, καταλήγετε πάντα σε ένα από τα δύο άκρα:1516- επιθετική προσωρινή αποθήκευση και κίνδυνος εμφάνισης παλαιών δεδομένων.17- δυναμική απόδοση παντού και απόδοση χειρότερη από όσο χρειάζεται.1819Το Cache Components χρησιμεύει ακριβώς για την αποφυγή αυτής της λανθασμένης επιλογής.2021## Το μοντέλο στην πράξη2223Με `cacheComponents: true`, μπορείτε να δηλώσετε τι είναι προσωρινά αποθηκευμένο χρησιμοποιώντας `"use cache"`. Στη συνέχεια, μπορείτε να συσχετίσετε τη διάρκεια και τις ετικέτες με `cacheLife()` και `cacheTag()`. Τα δυναμικά μέρη παραμένουν δυναμικά και μπορούν να απομονωθούν με `Suspense`.2425```mermaid26flowchart TD27 Request[Αίτημα χρήστη] --> Shell[Αποθηκευμένο κέλυφος]28 Request --> Dynamic[Δυναμικές τομές]29 Shell --> FirstPaint[Πρώτο γρήγορο περιεχόμενο]30 Dynamic --> Stream[Streaming μέσα στο Suspense]31 Stream --> Complete[Πλήρης σελίδα]32```3334Η ρύθμιση είναι μικρή:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647Η μεγάλη αλλαγή δεν είναι στις ρυθμίσεις. Είναι στο πώς ξεκινάτε να γράφετε τα στοιχεία.4849```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';5354async function getProduct(slug: string) {55 'use cache';5657 cacheLife('hours');58 cacheTag(`product:${slug}`);5960 return db.product.findUnique({ where: { slug } });61}6263async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);6566 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}7374async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}7879export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;8182 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```9293Η σελίδα δεν χρειάζεται να είναι ολόκληρη προσωρινή ή δυναμική. Το φύλλο προϊόντος μπορεί να είναι γρήγορο και επαναχρησιμοποιήσιμο. Το απόθεμα μπορεί να παραμείνει φρέσκο. Ο χρήστης βλέπει κάτι αμέσως, χωρίς να περιμένει το πιο αργό μέρος.9495## Το `use cache` είναι εκτελέσιμη τεκμηρίωση9697Αυτό που μου αρέσει στο `"use cache"` είναι ότι σε αναγκάζει να κάνεις μια ρητή πρόθεση. Όταν διαβάζετε μια συνάρτηση, καταλαβαίνετε αμέσως ότι κάποιος αποφάσισε: "αυτά τα δεδομένα μπορούν να επαναχρησιμοποιηθούν".9899Είναι ιδιαίτερα χρήσιμο όταν δεν χρησιμοποιείτε `fetch`. Πολλές εφαρμογές διαβάζουν δεδομένα από Prisma, Drizzle, εσωτερικά SDK, πελάτες CMS ή λειτουργίες υπηρεσιών. Σε αυτές τις περιπτώσεις η παλιά συλλογιστική που βασιζόταν μόνο στις επιλογές `fetch` δεν ήταν αρκετή.100101Ένας εμπειρικός κανόνας:102103- περιεχόμενο cachea σχετικά σταθερό.104- Χρησιμοποιήστε κοκκώδεις ετικέτες.105- αφήνει δυναμικά δικαιώματα, περιόδους σύνδεσης, καλάθια, ειδοποιήσεις και καταστάσεις συναλλαγών.106- βάλτε αργά εξαρτήματα μέσα `Suspense`.107- μετρήστε πριν πείτε "βελτιώσαμε την απόδοση".108109## Ακυρώστε χωρίς να τα πετάξετε όλα110111Η κρυφή μνήμη είναι χρήσιμη μόνο εάν μπορείτε να την ενημερώσετε με ακρίβεια. Εδώ τα `cacheTag`, `revalidateTag` και `updateTag` γίνονται σημαντικά.112113Παράδειγμα:114115```typescript116'use server';117118import { updateTag } from 'next/cache';119120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125126 updateTag(`product:${productId}`);127}128```129130Η σημαντική λεπτομέρεια είναι η ετικέτα. Το `product:${productId}` λέει ένα ακριβές όριο. Το `products` λέει έναν τεράστιο κουβά. Στην αρχή ο τεράστιος κάδος είναι άνετος. μετά από μερικούς μήνες γίνεται ο λόγος που ακυρώνετε μισή εφαρμογή για να αλλάξετε έναν τίτλο.131132## Stable Turbopack: το κομμάτι που ακούτε κάθε μέρα133134Το Next.js 16 φέρνει το Turbopack στο κέντρο για ανάπτυξη και κατασκευή. Δεν είναι το πιο ποιητικό χαρακτηριστικό, αλλά είναι αυτό που νιώθεις ενώ εργάζεσαι: διακομιστής που ξεκινά νωρίτερα, ταχύτερη ανανέωση, δομές που σταματούν να αισθάνονται σαν ένα αναγκαστικό διάλειμμα για καφέ.135136Τούτου λεχθέντος, δεν θα μετεγκαταστήσω μια βάση κώδικα γεμάτη προσαρμοσμένες προσθήκες με κλειστά μάτια. θα ελεγχα:137138- τοπική κατασκευή?139- μη τυποποιημένη εισαγωγή?140- MDX, SVG και CSS.141- Απομένουν προσθήκες πακέτου ιστού.142- κρίσιμες σελίδες?143- διαφορές στους χρόνους κατασκευής.144145Για νέα έργα, θα ξεκινούσα από την προεπιλογή. Για τους ώριμους, θα έκανα μια μετρημένη μετανάστευση.146147## React Compiler: αφαιρέστε το θόρυβο, όχι τη σκέψη148149Το React Compiler 1.0 είναι σταθερό και το Next.js 16 το υποστηρίζει με `reactCompiler`. Η υπόσχεση είναι να μειωθεί πολύ η χειροκίνητη απομνημόνευση: λιγότερα `memo`, λιγότερα `useMemo`, λιγότερα `useCallback` που χρησιμοποιούνται "για ασφάλεια".150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Δεν θα το αντιμετώπιζα σαν μαγική σκόνη. Ο μεταγλωττιστής βοηθάει όταν ο κώδικας ακολουθεί καλά τους κανόνες του React. Εάν τα εξαρτήματα έχουν περίεργες παρενέργειες, κρυφές μεταλλάξεις ή κακώς χρησιμοποιημένα άγκιστρα, αυτό πρέπει πρώτα να διορθωθεί.163164Ο υγιεινός τρόπος για να το δοκιμάσετε:1651661. ενημέρωση `eslint-plugin-react-hooks`;1672. διόρθωση πραγματικών παραβιάσεων·1683. ενεργοποιήστε το σε ελεγχόμενη περιοχή.1694. Μέτρηση του χρόνου κατασκευής και της συμπεριφοράς.1705. αφαιρέστε τη χειροκίνητη απομνημόνευση μόνο όταν δεν είναι πλέον απαραίτητη.171172Ο στόχος δεν είναι να σβήσετε κάθε `useMemo`. Ο στόχος είναι να σταματήσουμε να γράφουμε προληπτική απομνημόνευση γιατί φοβόμαστε την απόδοση.173174## `proxy.ts` και το όριο δικτύου175176Το παλιό `middleware.ts` γίνεται `proxy.ts`. Είναι μια αλλαγή ονόματος, αλλά είναι λογικό: αυτό το αρχείο βρίσκεται στο όριο αιτήματος, δεν είναι παραδοσιακό γενικό ενδιάμεσο λογισμικό τύπου backend.177178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188189 return NextResponse.next();190}191```192193Ο κανόνας εδώ είναι απλός: κρατήστε το μικρό. Ανακατεύθυνση, δρομολόγηση εξουσιοδότησης, κεφαλίδες, βασικές επανεγγραφές. Αν αρχίσει να φαίνεται σαν δεύτερο backend, μάλλον κάνει πάρα πολλά.194195## Πώς πραγματικά θα μεταναστεύσω196197Δεν θα ενεργοποιούσα όλες τις λειτουργίες ταυτόχρονα. Θα έκανα αυτό:1981991. Ενημερώνω το Next, το React και το React DOM.2002. Ξεκινάω το επίσημο codemod.2013. Διορθώνω τις αλλαγές σπασίματος στα `params`, `searchParams`, `cookies()`, `headers()` και `draftMode()`;2024. Κάνω μετεγκατάσταση `middleware.ts` σε `proxy.ts`;2035. Ελέγχω κατασκευές και κρίσιμες σελίδες.2046. Ενεργοποιώ τα στοιχεία προσωρινής μνήμης σε μια ενότητα όπου η κρυφή μνήμη δημιουργεί τριβή.2057. Ορίζω συμβάσεις για ετικέτες και ακύρωση.2068. Δοκιμάζω το React Compiler ξεχωριστά.2079. σύγκριση μετρήσεων πριν και μετά.208209Η καλή μετανάστευση δεν είναι αυτή που χρησιμοποιεί όλες τις νέες δυνατότητες. Αυτό είναι που κάνει τη συμπεριφορά της εφαρμογής πιο ευανάγνωστη.210211## Τι αλλάζει στον τρόπο σκέψης212213Το πιο χρήσιμο πράγμα για το Next.js 16 είναι ότι σας αναγκάζει να ονομάσετε καλύτερα τις προθέσεις. Μια συνάρτηση δεν είναι απλώς "πάρτε το προϊόν από τη βάση δεδομένων". Είναι "πάρτε το προϊόν, μπορώ να το κάνω cache για ώρες, το ακυρώνω με αυτήν την ετικέτα". Ένα στοιχείο δεν είναι απλώς "απόδοση της σελίδας". Είναι "αυτό είναι το γρήγορο κέλυφος, αυτό το κομμάτι είναι προσωπικό, αυτό έρχεται σε ροή."214215Στην αρχή φαίνεται σαν περισσότερη δουλειά. Τότε γίνεται μια μορφή ηρεμίας. Οι αποφάσεις απόδοσης δεν κρύβονται πλέον σε έναν συνδυασμό προεπιλογών, ευρετικών και φυλετικής μνήμης. Είναι στον κώδικα.216217## Χρήσιμες πηγές218219- [Σημειώσεις έκδοσης Next.js 16](https://nextjs.org/blog/next-16)220- [Στοιχεία προσωρινής μνήμης - Έγγραφα Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [χρήση προσωρινής μνήμης - Έγγραφα Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [React Compiler v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16, Cache Components και React Compiler: τι πραγματικά αλλάζειlines 1-223 (END) — press q to close