فارسی

API unstable_cache در Next.js را برای کنترل دقیق کش داده، بهبود عملکرد و تجربه کاربری در برنامه‌های پویا کاوش کنید.

unstable_cache در Next.js: کنترل دقیق کش برای برنامه‌های پویا

Next.js انقلابی در توسعه وب ایجاد کرده است و ویژگی‌های قدرتمندی برای ساخت برنامه‌های کاربردی با عملکرد بالا و مقیاس‌پذیر ارائه می‌دهد. یکی از نقاط قوت اصلی آن، مکانیسم کشینگ قدرتمند آن است که به توسعه‌دهندگان اجازه می‌دهد تا واکشی داده و رندرینگ را برای تجربه کاربری روان‌تر بهینه کنند. در حالی که Next.js استراتژی‌های مختلف کشینگ را ارائه می‌دهد، API unstable_cache سطح جدیدی از کنترل دقیق را ارائه می‌دهد و به توسعه‌دهندگان این امکان را می‌دهد که رفتار کشینگ را متناسب با نیازهای خاص برنامه‌های پویای خود تنظیم کنند. این مقاله به بررسی API unstable_cache، قابلیت‌ها، مزایا و کاربردهای عملی آن می‌پردازد.

درک کشینگ در Next.js

قبل از پرداختن به unstable_cache، درک لایه‌های مختلف کشینگ در Next.js ضروری است. Next.js از چندین مکانیسم کشینگ برای بهبود عملکرد استفاده می‌کند:

در حالی که این مکانیسم‌های کشینگ قدرتمند هستند، ممکن است همیشه سطح کنترل مورد نیاز برای برنامه‌های پیچیده و پویا را فراهم نکنند. اینجاست که unstable_cache وارد عمل می‌شود.

معرفی API `unstable_cache`

API unstable_cache در Next.js به توسعه‌دهندگان اجازه می‌دهد تا استراتژی‌های کشینگ سفارشی را برای عملیات واکشی داده فردی تعریف کنند. این API کنترل دقیقی بر موارد زیر فراهم می‌کند:

این API "ناپایدار" (unstable) در نظر گرفته می‌شود زیرا هنوز در حال توسعه است و ممکن است در نسخه‌های آینده Next.js دستخوش تغییر شود. با این حال، عملکرد ارزشمندی برای سناریوهای پیشرفته کشینگ ارائه می‌دهد.

unstable_cache چگونه کار می‌کند

تابع unstable_cache دو آرگومان اصلی می‌گیرد:

  1. یک تابع که داده را واکشی یا محاسبه می‌کند: این تابع بازیابی یا محاسبه واقعی داده را انجام می‌دهد.
  2. یک شیء گزینه‌ها (options object): این شیء گزینه‌های کشینگ مانند TTL، تگ‌ها و کلید را مشخص می‌کند.

در اینجا یک مثال ساده از نحوه استفاده از unstable_cache آورده شده است:

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // شبیه‌سازی واکشی داده از یک API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`] }
  )();
}

export default async function Page({ params }: { params: { id: string } }) {
  const data = await getData(params.id);
  return 
{data.value}
; }

در این مثال:

ویژگی‌ها و گزینه‌های کلیدی `unstable_cache`

۱. زمان بقا (Time-to-Live - TTL)

گزینه revalidate (که در نسخه‌های آزمایشی قبلی `ttl` نام داشت) حداکثر زمانی (به ثانیه) را مشخص می‌کند که داده‌های کش شده معتبر در نظر گرفته می‌شوند. پس از این زمان، کش در درخواست بعدی مجدداً اعتبارسنجی می‌شود.

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // شبیه‌سازی واکشی داده از یک API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`], revalidate: 60 } // کش برای ۶۰ ثانیه
  )();
}

در این مثال، داده برای ۶۰ ثانیه کش می‌شود. پس از ۶۰ ثانیه، درخواست بعدی باعث اعتبارسنجی مجدد شده، داده‌های تازه از API واکشی شده و کش به‌روزرسانی می‌شود.

نکته کلی: هنگام تنظیم مقادیر TTL، فرکانس به‌روزرسانی داده‌ها را در نظر بگیرید. برای داده‌هایی که به طور مکرر تغییر می‌کنند، TTL کوتاه‌تر مناسب است. برای داده‌های نسبتاً ثابت، TTL طولانی‌تر می‌تواند به طور قابل توجهی عملکرد را بهبود بخشد.

۲. تگ‌های کش (Cache Tags)

تگ‌های کش به شما این امکان را می‌دهند که داده‌های کش شده مرتبط را گروه‌بندی کرده و آنها را به صورت جمعی بی‌اعتبار کنید. این ویژگی زمانی مفید است که به‌روزرسانی یک بخش از داده بر سایر داده‌های مرتبط تأثیر بگذارد.

import { unstable_cache, revalidateTag } from 'next/cache';

async function getProduct(id: string) {
  return unstable_cache(
    async () => {
      // شبیه‌سازی واکشی داده محصول از یک API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const product = { id: id, name: `Product ${id}`, price: Math.random() * 100 };
      return product;
    },
    ["product", id],
    { tags: ["products", `product:${id}`] }
  )();
}

async function getCategoryProducts(category: string) {
  return unstable_cache(
    async () => {
      // شبیه‌سازی واکشی محصولات بر اساس دسته‌بندی از یک API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const products = Array.from({ length: 3 }, (_, i) => ({ id: `${category}-${i}`, name: `Product ${category}-${i}`, price: Math.random() * 100 }));
      return products;
    },
    ["categoryProducts", category],
    { tags: ["products", `category:${category}`] }
  )();
}

// بی‌اعتبار کردن کش برای همه محصولات و یک محصول خاص
async function updateProduct(id: string, newPrice: number) {
  // شبیه‌سازی به‌روزرسانی محصول در پایگاه داده
  await new Promise((resolve) => setTimeout(resolve, 500));

  // بی‌اعتبار کردن کش برای محصول و دسته‌بندی محصولات
  revalidateTag("products");
  revalidateTag(`product:${id}`);

  return { success: true };
}

در این مثال:

نکته کلی: از نام‌های تگ معنادار و سازگار استفاده کنید. یک استراتژی تگ‌گذاری که با مدل داده شما هماهنگ باشد، ایجاد کنید.

۳. تولید کلید کش

کلید کش برای شناسایی داده‌های کش شده استفاده می‌شود. به طور پیش‌فرض، unstable_cache بر اساس آرگومان‌های ارسال شده به تابع، یک کلید تولید می‌کند. با این حال، شما می‌توانید فرآیند تولید کلید را با استفاده از آرگومان دوم به `unstable_cache` که یک آرایه است و به عنوان کلید عمل می‌کند، سفارشی کنید. وقتی هر یک از آیتم‌های موجود در آرایه تغییر کند، کش بی‌اعتبار می‌شود.

import { unstable_cache } from 'next/cache';

async function getData(userId: string, sortBy: string) {
  return unstable_cache(
    async () => {
      // شبیه‌سازی واکشی داده از یک API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { userId: userId, sortBy: sortBy, value: `Data for user ${userId}, sorted by ${sortBy}` };
      return data;
    },
    [userId, sortBy],
    { tags: ["user-data", `user:${userId}`] }
  )();
}

در این مثال، کلید کش بر اساس پارامترهای userId و sortBy است. این تضمین می‌کند که کش هنگام تغییر هر یک از این پارامترها بی‌اعتبار شود.

نکته کلی: اطمینان حاصل کنید که استراتژی تولید کلید کش شما سازگار است و تمام عوامل مرتبطی که بر داده‌ها تأثیر می‌گذارند را در نظر می‌گیرد. برای ایجاد یک کلید منحصر به فرد از ساختارهای داده پیچیده، استفاده از یک تابع هش را در نظر بگیرید.

۴. اعتبارسنجی مجدد دستی

تابع `revalidateTag` به شما امکان می‌دهد تا به صورت دستی کش را برای داده‌های مرتبط با تگ‌های خاص بی‌اعتبار کنید. این ویژگی زمانی مفید است که نیاز دارید کش را در پاسخ به رویدادهایی که مستقیماً توسط درخواست کاربر ایجاد نشده‌اند، مانند یک کار پس‌زمینه (background job) یا یک وب‌هوک (webhook)، به‌روزرسانی کنید.

import { revalidateTag } from 'next/cache';

async function handleWebhook(payload: any) {
  // پردازش محتوای وب‌هوک

  // بی‌اعتبار کردن کش برای داده‌های مرتبط
  revalidateTag("products");
  revalidateTag(`product:${payload.productId}`);
}

نکته کلی: از اعتبارسنجی مجدد دستی به صورت استراتژیک استفاده کنید. بی‌اعتبار کردن بیش از حد می‌تواند مزایای کشینگ را از بین ببرد، در حالی که بی‌اعتبار کردن کمتر از حد می‌تواند منجر به داده‌های کهنه شود.

موارد استفاده عملی برای `unstable_cache`

۱. محتوای پویا با به‌روزرسانی‌های نادر

برای وب‌سایت‌هایی با محتوای پویا که خیلی زیاد تغییر نمی‌کند (مانند پست‌های وبلاگ، مقالات خبری)، می‌توانید از unstable_cache با TTL طولانی‌تر برای کش کردن داده‌ها برای دوره‌های طولانی استفاده کنید. این کار بار روی بک‌اند شما را کاهش داده و زمان بارگذاری صفحه را بهبود می‌بخشد.

۲. داده‌های مختص کاربر

برای داده‌های مختص کاربر (مانند پروفایل‌های کاربری، سبدهای خرید)، می‌توانید از unstable_cache با کلیدهای کش که شامل شناسه کاربر است، استفاده کنید. این تضمین می‌کند که هر کاربر داده‌های خود را می‌بیند و کش هنگام تغییر داده‌های کاربر بی‌اعتبار می‌شود.

۳. داده‌های لحظه‌ای با تحمل داده‌های کهنه

برای برنامه‌هایی که داده‌های لحظه‌ای نمایش می‌دهند (مانند قیمت سهام، فیدهای شبکه‌های اجتماعی)، می‌توانید از unstable_cache با TTL کوتاه برای ارائه به‌روزرسانی‌های تقریباً لحظه‌ای استفاده کنید. این کار تعادلی بین نیاز به داده‌های به‌روز و مزایای عملکردی کشینگ برقرار می‌کند.

۴. تست A/B

در طول تست A/B، مهم است که نسخه آزمایشی اختصاص داده شده به کاربر را کش کنید تا تجربه ثابتی تضمین شود. `unstable_cache` می‌تواند برای کش کردن نسخه انتخاب شده با استفاده از شناسه کاربر به عنوان بخشی از کلید کش استفاده شود.

مزایای استفاده از `unstable_cache`

ملاحظات و بهترین شیوه‌ها

مقایسه `unstable_cache` با کشینگ `fetch` API

Next.js همچنین قابلیت‌های کشینگ داخلی را از طریق fetch API فراهم می‌کند. به طور پیش‌فرض، Next.js به طور خودکار نتایج درخواست‌های fetch را کش می‌کند. با این حال، unstable_cache انعطاف‌پذیری و کنترل بیشتری نسبت به کشینگ fetch API ارائه می‌دهد.

در اینجا مقایسه‌ای بین این دو رویکرد آورده شده است:

ویژگی `unstable_cache` `fetch` API
کنترل بر TTL به صراحت با گزینه revalidate قابل تنظیم است. به طور ضمنی توسط Next.js مدیریت می‌شود، اما می‌توان با گزینه revalidate در گزینه‌های fetch بر آن تأثیر گذاشت.
تگ‌های کش از تگ‌های کش برای بی‌اعتبار کردن داده‌های مرتبط پشتیبانی می‌کند. پشتیبانی داخلی برای تگ‌های کش وجود ندارد.
سفارشی‌سازی کلید کش امکان سفارشی‌سازی کلید کش با آرایه‌ای از مقادیر که برای ساخت کلید استفاده می‌شوند را فراهم می‌کند. گزینه‌های سفارشی‌سازی محدود. کلید از URL واکشی مشتق می‌شود.
اعتبارسنجی مجدد دستی از اعتبارسنجی مجدد دستی با revalidateTag پشتیبانی می‌کند. پشتیبانی محدود برای اعتبارسنجی مجدد دستی.
دقت کشینگ امکان کش کردن عملیات واکشی داده فردی را فراهم می‌کند. عمدتاً بر کش کردن پاسخ‌های HTTP متمرکز است.

به طور کلی، از کشینگ fetch API برای سناریوهای ساده واکشی داده که رفتار کشینگ پیش‌فرض کافی است، استفاده کنید. از unstable_cache برای سناریوهای پیچیده‌تر که نیاز به کنترل دقیق بر رفتار کشینگ دارید، استفاده کنید.

آینده کشینگ در Next.js

API unstable_cache گام مهمی رو به جلو در قابلیت‌های کشینگ Next.js است. با تکامل این API، می‌توانیم انتظار داشته باشیم که ویژگی‌های قدرتمندتر و انعطاف‌پذیری بیشتری در مدیریت کشینگ داده‌ها ببینیم. به‌روز بودن با آخرین تحولات در کشینگ Next.js برای ساخت برنامه‌های کاربردی با عملکرد بالا و مقیاس‌پذیر بسیار مهم است.

نتیجه‌گیری

API unstable_cache در Next.js به توسعه‌دهندگان کنترل بی‌سابقه‌ای بر کشینگ داده‌ها ارائه می‌دهد و آنها را قادر می‌سازد تا عملکرد و تجربه کاربری را در برنامه‌های پویا بهینه کنند. با درک ویژگی‌ها و مزایای unstable_cache، می‌توانید از قدرت آن برای ساخت برنامه‌های وب سریع‌تر، مقیاس‌پذیرتر و پاسخ‌گوتر استفاده کنید. به یاد داشته باشید که استراتژی کشینگ خود را با دقت در نظر بگیرید، مقادیر TTL مناسب را انتخاب کنید، کلیدهای کش خود را به طور مؤثر طراحی کنید و عملکرد کش خود را برای اطمینان از نتایج بهینه نظارت کنید. آینده کشینگ در Next.js را در آغوش بگیرید و پتانسیل کامل برنامه‌های وب خود را آزاد کنید.