استخدام التخزين المؤقت (use cache)

يسمح لك توجيه use cache بوضع علامة على مسار أو مكون React أو دالة على أنها قابلة للتخزين المؤقت. يمكن استخدامه في أعلى الملف للإشارة إلى أنه يجب تخزين جميع الصادرات في الملف مؤقتًا، أو مضمنًا في أعلى الدالة أو المكون لتخزين القيمة المرجعة مؤقتًا.

الاستخدام

use cache هو حاليًا ميزة تجريبية. لتمكينها، أضف خيار useCache إلى ملف next.config.ts الخاص بك:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    useCache: true,
  },
}

export default nextConfig
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    useCache: true,
  },
}

module.exports = nextConfig

معلومة جيدة: يمكن أيضًا تمكين use cache باستخدام خيار dynamicIO.

ثم أضف use cache على مستوى الملف أو المكون أو الدالة:

// مستوى الملف
'use cache'

export default async function Page() {
  // ...
}

// مستوى المكون
export async function MyComponent() {
  'use cache'
  return <></>
}

// مستوى الدالة
export async function getData() {
  'use cache'
  const data = await fetch('/api/data')
  return data
}

كيفية عمل use cache

مفاتيح التخزين المؤقت

يتم إنشاء مفتاح إدخال التخزين المؤقت باستخدام نسخة مسلسلة من مدخلاته، والتي تشمل:

  • معرف البناء (يتم إنشاؤه لكل بناء)
  • معرف الدالة (معرف فريد وآمن للدالة)
  • الوسائط (أو الخصائص) القابلة للتحويل إلى سلسلة (serializable).

الوسائط التي يتم تمريرها إلى الدالة المخزنة مؤقتًا، وكذلك أي قيم تقرأها من النطاق الأصلي تصبح تلقائيًا جزءًا من المفتاح. هذا يعني أنه سيتم إعادة استخدام نفس إدخال التخزين المؤقت طالما كانت المدخلات هي نفسها.

وسائط غير قابلة للتحويل إلى سلسلة

أي وسائط أو خصائص أو قيم مغلقة غير قابلة للتحويل إلى سلسلة ستصبح مراجع داخل الدالة المخزنة مؤقتًا، ويمكن تمريرها فقط دون فحص أو تعديل. لن تصبح هذه القيم غير القابلة للتحويل إلى سلسلة جزءًا من مفتاح التخزين المؤقت وستتم تعبئتها في وقت الطلب.

على سبيل المثال، يمكن أن تأخذ الدالة المخزنة مؤقتًا JSX كخاصية children وتُرجع <div>{children}</div>، لكنها لن تكون قادرة على فحص كائن children الفعلي. هذا يسمح لك بتداخل محتوى غير مخزن مؤقتًا داخل مكون مخزن مؤقتًا.

function CachedComponent({ children }: { children: ReactNode }) {
  'use cache'
  return <div>{children}</div>
}
function CachedComponent({ children }) {
  'use cache'
  return <div>{children}</div>
}

قيم الإرجاع

يجب أن تكون القيمة المرجعة من الدالة القابلة للتخزين المؤقت قابلة للتحويل إلى سلسلة. هذا يضمن أنه يمكن تخزين البيانات المؤقتة واستردادها بشكل صحيح.

use cache في وقت البناء

عند استخدامه في أعلى تخطيط (layout) أو صفحة (page)، سيتم تقديم مقطع المسار مسبقًا، مما يسمح بإعادة التحقق منه لاحقًا.

هذا يعني أنه لا يمكن استخدام use cache مع واجهات برمجة التطبيقات في وقت الطلب مثل cookies أو headers.

use cache في وقت التشغيل

على الخادم، سيتم تخزين إدخالات التخزين المؤقت للمكونات أو الدوال الفردية في الذاكرة.

ثم على العميل، سيتم تخزين أي محتوى يتم إرجاعه من ذاكرة التخزين المؤقت للخادم في ذاكرة المتصفح لمدة الجلسة أو حتى يتم إعادة التحقق منها.

أثناء إعادة التحقق

بشكل افتراضي، لدى use cache فترة إعادة تحقق من جانب الخادم تبلغ 15 دقيقة. بينما قد تكون هذه الفترة مفيدة للمحتوى الذي لا يحتاج إلى تحديثات متكررة، يمكنك استخدام واجهات برمجة التطبيقات cacheLife و cacheTag لتكوين متى يجب إعادة تحقق إدخالات التخزين المؤقت الفردية.

  • cacheLife: تكوين عمر إدخال التخزين المؤقت.
  • cacheTag: إنشاء علامات لإعادة التحقق عند الطلب.

تتكامل كل من واجهات برمجة التطبيقات هذه عبر طبقات التخزين المؤقت للعميل والخادم، مما يعني أنه يمكنك تكوين دلالات التخزين المؤقت في مكان واحد وتطبيقها في كل مكان.

راجع وثائق API لكل من cacheLife و cacheTag لمزيد من المعلومات.

أمثلة

تخزين مسار كامل مؤقتًا باستخدام use cache

لتقديم مسار كامل مسبقًا، أضف use cache إلى أعلى كلا ملفي layout و page. يتم التعامل مع كل من هذه المقاطع كنقاط دخول منفصلة في تطبيقك، وسيتم تخزينها مؤقتًا بشكل مستقل.

'use cache'

export default function Layout({ children }: { children: ReactNode }) {
  return <div>{children}</div>
}
'use cache'

export default function Layout({ children }) {
  return <div>{children}</div>
}

سيتم توريث سلوك التخزين المؤقت لـ page من قبل أي مكونات مستوردة ومتداخلة في ملف page.

'use cache'

async function Users() {
  const users = await fetch('/api/users')
  // تكرار خلال المستخدمين
}

export default function Page() {
  return (
    <main>
      <Users />
    </main>
  )
}
'use cache'

async function Users() {
  const users = await fetch('/api/users')
  // تكرار خلال المستخدمين
}

export default function Page() {
  return (
    <main>
      <Users />
    </main>
  )
}

معلومة جيدة:

  • إذا تمت إضافة use cache فقط إلى layout أو page، فسيتم تخزين هذا المقطع من المسار وأي مكونات مستوردة إليه فقط مؤقتًا.
  • إذا كان أي من العناصر الفرعية المتداخلة في المسار يستخدم واجهات برمجة التطبيقات الديناميكية، فسيتم استبعاد المسار من التقديم المسبق.

تخزين ناتج مكون مؤقتًا باستخدام use cache

يمكنك استخدام use cache على مستوى المكون لتخزين أي عمليات جلب أو حسابات تتم داخل هذا المكون. سيتم إعادة استخدام إدخال التخزين المؤقت طالما أن الخصائص المسلسلة تنتج نفس القيمة في كل مثيل.

export async function Bookings({ type = 'haircut' }: BookingsProps) {
  'use cache'
  async function getBookingsData() {
    const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
    return data
  }
  return //...
}

interface BookingsProps {
  type: string
}
export async function Bookings({ type = 'haircut' }) {
  'use cache'
  async function getBookingsData() {
    const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
    return data
  }
  return //...
}

تخزين ناتج دالة مؤقتًا باستخدام use cache

نظرًا لأنه يمكنك إضافة use cache إلى أي دالة غير متزامنة، فأنت لست مقيدًا بتخزين المكونات أو المسارات فقط. قد ترغب في تخزين طلب شبكة أو استعلام قاعدة بيانات أو عملية حسابية بطيئة مؤقتًا.

export async function getData() {
  'use cache'

  const data = await fetch('/api/data')
  return data
}
export async function getData() {
  'use cache'

  const data = await fetch('/api/data')
  return data
}

التداخل

إذا كنت بحاجة إلى تمرير وسائط غير قابلة للتحويل إلى سلسلة إلى دالة قابلة للتخزين المؤقت، يمكنك تمريرها كـ children. هذا يعني أن مرجع children يمكن أن يتغير دون التأثير على إدخال التخزين المؤقت.

export default async function Page() {
  const uncachedData = await getData()
  return (
    <CacheComponent>
      <DynamicComponent data={uncachedData} />
    </CacheComponent>
  )
}

async function CacheComponent({ children }: { children: ReactNode }) {
  'use cache'
  const cachedData = await fetch('/api/cached-data')
  return (
    <div>
      <PrerenderedComponent data={cachedData} />
      {children}
    </div>
  )
}
export default async function Page() {
  const uncachedData = await getData()
  return (
    <CacheComponent>
      <DynamicComponent data={uncachedData} />
    </CacheComponent>
  )
}

async function CacheComponent({ children }) {
  'use cache'
  const cachedData = await fetch('/api/cached-data')
  return (
    <div>
      <PrerenderedComponent data={cachedData} />
      {children}
    </div>
  )
}

يمكنك أيضًا تمرير إجراءات الخادم (Server Actions) عبر المكونات المخزنة مؤقتًا إلى مكونات العميل دون استدعائها داخل الدالة القابلة للتخزين المؤقت.

import ClientComponent from './ClientComponent'

export default async function Page() {
  const performUpdate = async () => {
    'use server'
    // تنفيذ بعض التحديثات من جانب الخادم
    await db.update(...)
  }

  return <CacheComponent performUpdate={performUpdate} />
}

async function CachedComponent({
  performUpdate,
}: {
  performUpdate: () => Promise<void>
}) {
  'use cache'
  // لا تستدع performUpdate هنا
  return <ClientComponent action={performUpdate} />
}
import ClientComponent from './ClientComponent'

export default async function Page() {
  const performUpdate = async () => {
    'use server'
    // تنفيذ بعض التحديثات من جانب الخادم
    await db.update(...)
  }

  return <CacheComponent performUpdate={performUpdate} />
}

async function CachedComponent({ performUpdate }) {
  'use cache'
  // لا تستدع performUpdate هنا
  return <ClientComponent action={performUpdate} />
}
'use client'

export default function ClientComponent({
  action,
}: {
  action: () => Promise<void>
}) {
  return <button onClick={action}>تحديث</button>
}
'use client'

export default function ClientComponent({ action }) {
  return <button onClick={action}>تحديث</button>
}

دعم المنصة

خيار النشرمدعوم
خادم Node.jsنعم
حاوية Dockerنعم
تصدير ثابتلا
المحولاتحسب المنصة

تعلم كيفية تكوين التخزين المؤقت عند استضافة Next.js ذاتيًا.

تاريخ الإصدارات

الإصدارالتغييرات
v15.0.0تم تقديم "use cache" كميزة تجريبية.