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` وواجهات برمجة التطبيقات الجديدة للإبطال مهمة، ولكنها تدور حول نفس المشكلة: إنشاء تطبيقات سريعة دون الحاجة إلى تخمين ما قرره إطار العمل خلف الكواليس.78## لأن هذا الشيء مهم910في التطبيق الحقيقي، لا يكون لديك فقط "صفحات ثابتة" و"صفحات ديناميكية". لديك قطع مختلفة باحتياجات مختلفة.1112قد تتغير ورقة المنتج عدة مرات في اليوم. قد يتغير السعر في كثير من الأحيان. يجب أن يكون التوفر مباشرًا تقريبًا. اسم المستخدم شخصي. يمكن دفق التعليقات. يمكن أن يكون الشريط الجانبي مستقرًا. العربة لا.1314إذا تعاملت مع كل شيء كوحدة واحدة، فسوف ينتهي بك الأمر دائمًا إلى أحد النقيضين:1516- التخزين المؤقت العدواني وخطر رؤية البيانات القديمة؛17- العرض الديناميكي في كل مكان والأداء أسوأ من اللازم.1819تعمل مكونات ذاكرة التخزين المؤقت على وجه التحديد على تجنب هذا الاختيار الخاطئ.2021## النموذج على أرض الواقع2223باستخدام `cacheComponents: true`، يمكنك الإعلان عن ما هو قابل للتخزين المؤقت باستخدام `"use cache"`. وبعد ذلك يمكنك ربط المدة والعلامات بـ `cacheLife()` و`cacheTag()`. تظل الأجزاء الديناميكية ديناميكية ويمكن عزلها باستخدام `Suspense`.2425```mermaid26flowchart TD27 Request[طلب المستخدم] --> Shell[قذيفة مخبأة]28 Request --> Dynamic[أقسام ديناميكية]29 Shell --> FirstPaint[أول محتوى سريع]30 Dynamic --> Stream[الجري داخل التشويق]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- محتوى ذاكرة التخزين المؤقت مستقر نسبيًا؛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## Turbopack المستقر: الجزء الذي تسمعه كل يوم133134يقوم Next.js 16 بإحضار Turbopack إلى مركز التطوير والبناء. إنها ليست الميزة الأكثر شاعرية، ولكنها الميزة التي تشعر بها أثناء العمل: الخادم الذي يبدأ مبكرًا، والتحديث الأسرع، والبنيات التي لا تشعر وكأنها استراحة قسرية لتناول القهوة.135136ومع ذلك، لن أقوم بترحيل قاعدة تعليمات برمجية مليئة بالمكونات الإضافية المخصصة وعيناي مغمضتان. أود أن أتحقق:137138- البناء المحلي139- استيراد غير قياسي140- MDX، SVG وCSS؛141- ملحقات Webpack المتبقية؛142- صفحات حرجة؛143- الاختلافات في أوقات البناء.144145بالنسبة للمشاريع الجديدة، سأبدأ من الافتراضي. بالنسبة للأشخاص الناضجين، سأقوم بهجرة محسوبة.146147## رد الفعل المترجم: إزالة الضوضاء، وليس الفكر148149React 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`. إنه تغيير في الاسم، ولكنه منطقي: يقع هذا الملف عند حدود الطلب، وهو ليس برنامجًا وسيطًا عامًا تقليديًا على نمط الواجهة الخلفية.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القاعدة هنا بسيطة: أبقِها صغيرة. إعادة التوجيه، توجيه المصادقة، الرؤوس، عمليات إعادة الكتابة الأساسية. إذا بدأت تشعر وكأنها واجهة خلفية ثانية، فمن المحتمل أنها تفعل الكثير.194195## كيف سأهاجر حقا196197لن أقوم بتشغيل جميع الميزات مرة واحدة. سأفعل هذا:1981991. أقوم بتحديث Next وReact وReact DOM؛2002. أقوم بتشغيل الكود الرسمي؛2013. أقوم بإصلاح التغييرات المعطلة على `params`، `searchParams`، `cookies()`، `headers()` و`draftMode()`؛2024. أقوم بترحيل `middleware.ts` إلى `proxy.ts`؛2035. أتحقق من الإصدارات والصفحات المهمة؛2046. أقوم بتمكين مكونات ذاكرة التخزين المؤقت في قسم حيث تؤدي ذاكرة التخزين المؤقت حاليًا إلى حدوث احتكاك؛2057. أقوم بتحديد اصطلاحات العلامات والإبطال؛2068. أحاول استخدام React Compiler بشكل منفصل؛2079. مقارنة المقاييس قبل وبعد.208209الترحيل الجيد ليس هو الذي يستخدم كافة الميزات الجديدة. وهذا ما يجعل سلوك التطبيق أكثر قابلية للقراءة.210211## ما يتغير في طريقة التفكير212213الشيء الأكثر فائدة في Next.js 16 هو أنه يجبرك على تسمية النوايا بشكل أفضل. الوظيفة ليست مجرد "الحصول على المنتج من قاعدة البيانات". إنها "احصل على المنتج، يمكنني تخزينه مؤقتًا لساعات، وأقوم بإبطاله باستخدام هذه العلامة". المكون ليس مجرد "عرض الصفحة". إنها "هذه هي القشرة السريعة، وهذه القطعة شخصية، وهذا يأتي عبر البث المباشر."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- [رد الفعل المترجم v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16، مكونات ذاكرة التخزين المؤقت ومترجم React: ما الذي يتغير بالفعلlines 1-223 (END) — press q to close