Next.js یک فریمورک شگفتانگیز است که نوشتن برنامههای React که رندر سمت سرور پیچیده دارند را بسیار آسانتر میکند، اما یک مشکل بزرگ وجود دارد. مکانیسم caching در Next.js بسیار پیچیده است و به راحتی میتواند منجر به ایجاد اشکالاتی در کد ما شود که دیباگ کردن و رفع آنها دشوار است.
اگر نمیدانیم مکانیسم caching در Next.js چگونه کار میکند، بهنظر میرسد که بهجای بهرهمندی از مزایای شگفتانگیز ذخیرهسازی قدرتمند Next.js، دائماً در حال مبارزه با آن هستیم. به همین دلیل در این مقاله قصد داریم تا نحوه عملکرد هر بخش از caching در Next.js را بررسی کنیم تا بتوانیم به راحتی از عملکرد باورنکردنی آن بهره ببریم.
در طول مقاله ممکن است با دو عبارت Build Time و Request Time روبهرو شویم. برای اطمینان از اینکه این موضوع باعث سردرگمی در کل مقاله نمیشود، اجازه دهید قبل از حرکت به جلو، آنها با هم بررسی کنیم.
Build Time به زمانی اشاره دارد که یک اپلیکیشن ساخته و اجرا میشود. هر چیزی که در طول این فرآیند cache میشود (بیشتر محتوای ثابت) بخشی از حافظه مربوط به Build Time خواهد بود و تنها زمانی به روز رسانی میشود که برنامه rebuilt و مجدداً deploy شود.
Request Time به زمانی اشاره دارد که کاربر صفحهای را درخواست میکند. به طور معمول، دادههایی که در Request Time ذخیره میشوند پویا هستند، زیرا ما میخواهیم آنها را مستقیماً از منبع داده در زمانی که کاربر درخواست میکند fetch کنیم.
درک مفهوم caching در Next.js در ابتدا میتواند کمی پیچیده به نظر برسد. زیرا که از چهار مکانیسم caching متمایز تشکیل شده است که هر کدام در مراحل مختلف برنامه ما عمل میکنند و به گونهای تعامل دارند که در ابتدا پیچیده به نظر میرسد.
در ادامه چهار مکانیسم caching در Next.js را داریم:
ما برای هر یک از موارد بالا نقشهای خاص آنها، جایی که ذخیره میشوند، مدت زمان آنها، نحوه مدیریت مؤثر آنها، راههایی برای باطل کردن cache و انصراف را بررسی خواهیم کرد.
در پایان این مقاله، درک کاملی از نحوه کار مکانیسمهای caching برای بهینهسازی عملکرد Next.js خواهیم داشت.
یکی از مشکلات رایج در React زمانی است که ما نیاز داریم تا اطلاعات یکسانی را در چندین مکان در یک صفحه نمایش دهیم. سادهترین گزینه این است که دادهها را در هر دو مکان مورد نیاز fetch کنیم. اما این کار ایدهآل نیست زیرا اکنون دو درخواست برای دریافت دادههای مشابه از سرور خود داریم. اینجاست که Request Memoization وارد میشود.
Request Memoization یک ویژگی React است که هر درخواستfetch
را که در طول چرخه، در یک سرور کامپوننت رندر میکنیم( به طوری کلی فقط به فرآیند رندر کردن همه کامپوننتهای یک صفحه اشاره دارد) در حافظه cache نگه میدارد. این بدان معناست که اگر ما یک درخواستfetch
را در یک کامپوننت انجام دهیم و سپس همان درخواستfetch
را در کامپوننت دیگر انجام دهیم، درخواستfetch
دوم در واقع درخواستی از سرور نخواهد داشت. در عوض، از مقدار cache شده از اولین درخواست fetch
استفاده خواهد کرد.
export default async function fetchUserData(userId) { // The `fetch` function is automatically cached by Next.js const res = await fetch(`https://api.example.com/users/${userId}`) return res.json(); } export default async function Page({ params }) { const user = await fetchUserData(params.id) return <> <h1>{user.name}</h1> <UserDetails id={params.id} /> </> } async function UserDetails({ id }) { const user = await fetchUserData(id) return <p>{user.name}</p> }
در کد بالا دو کامپوننت داریم: Page
و UserDetails
. اولین فراخوانی تابع fetchUserData()
در Page
یک درخواست fetch
درست مانند حالت عادی ایجاد میکند، اما مقدار بازگشتی آن درخواستfetch
در حافظه کش Request Memoization ذخیره میشود. دومین باری که fetchUserData
توسط کامپوننت UserDetails
فراخوانی میشود، در واقع درخواست fetch
جدیدی ایجاد نمیکند. در عوض، از مقدار ذخیره شده از اولین باری که این درخواست fetch
انجام شد استفاده میکند. این بهینهسازی کوچک با کاهش تعداد درخواستهای ارسال شده به سرور، عملکرد برنامه ما را به شدت افزایش میدهد. همچنین نوشتن کامپوننتها را آسانتر میکند زیرا در این صورت نیازی به نگرانی در مورد بهینهسازی درخواستهایfetch
نداریم.
مهم است بدانیم که این cache به طور کامل روی سرور ذخیره میشود، به این معنی که فقط درخواستهای fetch
ارسال شده از سرور کامپوننتها را در حافظه cache ذخیره میکند. همچنین، این cache در شروع هر درخواست به طور کامل پاک میشود، یعنی این که فقط برای مدت زمان یک چرخه رندر معتبر است. اما این موضوع یک مشکل نیست، زیرا تمام هدف این cache کاهش درخواستهایfetch
تکراری در یک چرخه رندر میباشد.
در نهایت، این cache فقط درخواستهای fetch
که با متد GET
انجام شدهاند را در حافظه cache ذخیره میکند. یک درخواست fetch
نیز باید دقیقاً همان پارامترها (URL و options) را داشته باشد تا بتواند به خاطر سپرده شود.
به طور پیشفرض React فقط درخواستهای fetch
را در حافظه cache ذخیره میکند، اما مواقعی وجود دارد که ممکن است بخواهیم انواع دیگر درخواستها مانند درخواستهای پایگاه داده را در حافظه cache ذخیره کنیم. برای این کار میتوانیم از تابع cache
React استفاده نماییم. تنها کاری که باید انجام دهیم این است که تابعی را که میخواهیم ذخیره کنیم بهcache
منتقل کرده و یک نسخه memoized شده از آن تابع را return کنیم.
import { cache } from "react" import { queryDatabase } from "./databaseClient" export const fetchUserData = cache(userId => { // Direct database query return queryDatabase("SELECT * FROM users WHERE id = ?", [userId]) })
در این کد بالا، اولین باری که fetchUserData()
فراخوانی میشود، مستقیماً در پایگاه داده پرس و جو میکند، زیرا هنوز هیچ نتیجه cache وجود ندارد. اما دفعه بعد که این تابع با همان userId
فراخوانی میشود، دادهها را از cache بازیابی میکند. درست مانند fetch
، این memoization فقط برای مدت یک render pass معتبر است و شبیه به fetch
memoization عمل میکند.
Revalidation فرآیند پاک کردن cache و به روز رسانی آن با دادههای جدید است. انجام این کار بسیار مهم میباشد زیرا اگر یک cache را هرگز به روز رسانی نکنیم، در نهایت دادههای آن قدیمی میشود. خوشبختانه، با وجود Request Memoization نیاز نیست درمورد این موضوع نگران باشیم. زیرا، این cache فقط برای مدت یک درخواست معتبر است و نیازی نیست ما آن را revalidate کنیم.
برای انصراف از این cache، میتوانیم یک signal
AbortController
را به عنوان پارامتر به درخواست fetch
ارسال کنیم.
async function fetchUserData(userId) { const { signal } = new AbortController() const res = await fetch(`https://api.example.com/users/${userId}`, { signal, }) return res.json() }
انجام این کار به React میگوید که این درخواست fetch
را در حافظه کش Request Memoization ذخیره نکند، اما انجام این کار توصیه نمیشود مگر اینکه دلیل خوبی برای آن داشته باشیم. زیرا این کش بسیار مفید است و میتواند عملکرد برنامه ما را به شدت بهبود بخشد.
نکتهای که باید با آن توجه کنیم این است که Request Memoization از نظر فنی یک ویژگی React است و منحصر به Next.js نیست. ما در این مقاله آن را به عنوان بخشی از مکانیسمهای caching در Next.js در نظر گرفتهایم، زیرا درک آن برای درک کامل فرآیند caching در Next.js ضروری است.
Request Memoization با جلوگیری از درخواست fetch
تکراری برای عملکرد بهتر برنامه ما عالی است، اما وقتی نوبت به کش کردن دادهها در بین درخواستها یا کاربران میرسد بیفایده است. این قسمت همان جایی است که Data Cache وارد میشود. این آخرین کشی است که Next.js قبل از اینکه واقعاً دادههای ما را از یک API یا پایگاه داده fetch کند، انجام میدهد و در چندین درخواست و یا کاربر پایدار است.
تصور کنید ما یک صفحه ساده داریم که از یک API درخواست میکند تا دادههای راهنمای یک یک شهر خاص را دریافت نماید.
export default async function Page({ params }) { const city = params.city const res = await fetch(`https://api.globetrotter.com/guides/${city}`) const guideData = await res.json() return ( <div> <h1>{guideData.title}</h1> <p>{guideData.content}</p> {/* Render the guide data */} </div> ) }
این دادههای راهنما هرگز تغییر نمیکنند. بنابراین منطقی نیست هر زمان که کسی به آن نیاز داشت همان لحظه fetch
کنیم. در عوض باید آن دادهها را در تمام درخواستها ذخیره کنیم تا فوراً برای کاربران آینده لود شود. به طور معمول، پیادهسازی این کار مشکل خواهد بود. اما خوشبختانه Next.js این کار را به شکل خودکار با Data Cache برای ما انجام میدهد.
بهطور پیشفرض، هر درخواست fetch
در سرور کامپوننت ما در Data Cache، که در سرور ذخیره میشود، ذخیره میگردد و برای همه درخواستهای بعدی مورد استفاده قرار میگیرد. این بدان معناست که اگر ۱۰۰ کاربر داشته باشیم که همگی یک داده را درخواست میکنند، Next.js فقط یک درخواست fetch به API میفرستد و سپس از آن دادههای ذخیره شده برای همه ۱۰۰ کاربر استفاده میکند. این کار یک افزایش عملکرد بزرگ به حساب میآید.
Data Cache با حافظه کش Request Memoization متفاوت است، زیرا دادههای این حافظه هرگز پاک نمیشوند، مگر اینکه ما به طور خاص به Next.js بگوییم این کار را انجام دهد. این دادهها حتی در سراسر deploymentها باقی میمانند. به این معنی که اگر نسخه جدیدی از برنامه خود را اجرا کنیم، Data Cache پاک نخواهد شد.
از آنجایی که Data Cache هرگز توسط Next.js پاک نمیشود، ما به روشی برای انتخاب revalidation نیاز داریم که فقط فرآیند حذف دادهها از کش را دربر میگیرد. در Next.js دو روش مختلف برای انجام این کار وجود دارد: اعتبار سنجی مجدد مبتنی بر زمان و اعتبار سنجی مجدد مبتنی بر تقاضا.
سادهترین راه برای تأیید اعتبار Data Cache، پاک کردن خودکار کش پس از یک دوره زمانی مشخص است. این کار میتواند با دو روش انجام شود.
const res = fetch(`https://api.globetrotter.com/guides/${city}`, { next: { revalidate: 3600 }, })
راه اول این است که گزینه next.revalidate
را به درخواست fetch
خود اضافه کنیم. این گزینه به Next.js میگوید که چند ثانیه باید دادههای ما را قبل از اینکه به عنوان داده قدیمی در نظر گرفته شوند، در کش نگه دارد. در مثال بالا، به Next.js میگوییم که هر یک ساعت یک بار حافظه cache را مجدداً تأیید کند.
راه دیگر برای تنظیم زمان اعتبار سنجی مجدد استفاده از گزینه revalidate
بخش پیکربندی است.
export const revalidate = 3600 export default async function Page({ params }) { const city = params.city const res = await fetch(`https://api.globetrotter.com/guides/${city}`) const guideData = await res.json() return ( <div> <h1>{guideData.title}</h1> <p>{guideData.content}</p> {/* Render the guide data */} </div> ) }
انجام این کار باعث میشود همه درخواستهای fetch
برای این صفحه، هر ساعت مجدداً تأیید شوند. مگر اینکه زمان اعتبارسنجی مجدد را روی مقدار خاص مورد نظر خود را تنظیم کرده باشیم.
یکی از مهمترین چیزهایی که باید با اعتبارسنجی مجدد مبتنی بر زمان درک کنیم این است که چگونه دادههای قدیمی را مدیریت میکند.
اولین باری که درخواست fetch
انجام میشود، دادهها را دریافت کرده و سپس در حافظه cache ذخیره میکند. هر درخواست fetch
جدیدی که در مدت زمان اعتبارسنجی مجدد ۱ ساعته که ما تنظیم میکنیم اتفاق میافتد، از دادههای ذخیرهشده استفاده میکند و درخواست fetch
جدید ایجاد نمیشود. پس از ۱ساعت، اولین درخواست fetch
که انجام میشود همچنان دادههای cache را برمیگرداند، اما درخواست fetch
را نیز برای دریافت دادههای جدید و ذخیره آنها در حافظه cache اجرا میکند. این بدان معناست که هر درخواست fetch
جدید پس از این درخواست، از دادههای ذخیرهشده جدید استفاده میکند. این الگو stale-while-revalidate نامیده میشود و رفتاری است که Next.js آن را به کار میگیرد.
اگر دادههای ما بر اساس یک برنامه منظم به روز رسانی نمیشوند، میتوانیم از اعتبارسنجی مجدد مبتنی بر تقاضا برای تأیید مجدد حافظه cache، تنها زمانی که دادههای جدید در دسترس باشد استفاده کنیم. این کار زمانی مفید است که میخواهیم حافظه cache را باطل کنیم و دادههای جدید را تنها زمانی که مقاله جدیدی منتشر میشود یا رویداد خاصی رخ میدهد، fetch کنیم.
این کار را میتوانیم به یکی از دو روش زیر انجام دهیم.
import { revalidatePath } from "next/cache" export async function publishArticle({ city }) { createArticle(city) revalidatePath(`/guides/${city}`) }
تابع revalidatePath
یک مسیر رشتهای را دریافت میکند و کش تمام درخواستهای fetch
در آن مسیر را پاک میکند.
اگر بخواهیم در درخواستهای fetch
برای اعتبارسنجی مجدد دقیقتر عمل کنیم، میتوانیم از تابع revalidateTag
استفاده کنیم.
const res = fetch(`https://api.globetrotter.com/guides/${city}`, { next: { tags: ["city-guides"] }, })
در اینجا، ما تگ city-guides
را به درخواست fetch
خود اضافه میکنیم تا بتوانیم آن را با revalidateTag
مورد هدف قرار دهیم.
import { revalidateTag } from "next/cache" export async function publishArticle({ city }) { createArticle(city) revalidateTag("city-guides") }
هنگامی کهrevalidateTag
را با یک رشته فراخوانی میکنیم، کش تمام درخواستهای fetch
با آن تگ را پاک میکند.
انصراف از Data Cache را میتوانیم به روشهای مختلفی انجام دهیم.
no-store
const res = fetch(`https://api.globetrotter.com/guides/${city}`, { cache: "no-store", })
با ارسال cache: "no-store"
به درخواست fetch
، به Next.js میگوییم که این درخواست را در Data Cache ذخیره نکند. این کار زمانی مفید است که ما دادههایی داریم که دائماً در حال تغییر هستند و میخواهیم هر بار آنها را به روز دریافت نماییم.
همچنین میتوانیم تابع noStore
را فراخوانی کنیم تا از Data Cache برای هر چیزی که در scope آن تابع است انصراف دهیم.
import { unstable_noStore as noStore } from "next/cache" function getGuide() { noStore() const res = fetch(`https://api.globetrotter.com/guides/${city}`) }
نکتهای که باید به آن توجه داشته باشیم این است که در حال حاضر، این یک ویژگی آزمایشی بوده و به همین دلیل پیشوند آن با unstable_ میباشد، اما در آینده، این روش به عنوان ترجیحی برای انصراف از Data Cache در Next.js استفاده میشود.
این یک راه واقعا عالی برای انصراف از کش کردن بر اساس هر کامپوننت یا هر تابع است، زیرا سایر روشهای انصراف از Data Cache کل صفحه را تحت تاثیر قرار میدهند.
export const dynamic = 'force-dynamic'
اگر بخواهیم رفتار کش را برای کل صفحه و نه فقط یک درخواست fetch
خاص تغییر دهیم، میتوانیم این گزینه پیکربندی بخش را به سطح بالای فایل خود اضافه کنیم. این باعث میشود تا صفحه پویا باشد و به طور کامل از Data Cache انصراف دهد.
export const dynamic = "force-dynamic"
export const revalidate = 0
راه دیگر برای حذف کل صفحه از Data Cache، استفاده از گزینه revalidate
بخش پیکربندی با مقدار ۰ است.
export const revalidate = 0
این خط تقریباً معادل cache: "no-store"
در سطح صفحه است. این گزینه برای همه درخواستهای موجود در صفحه اعمال میشود و اطمینان حاصل میکند که هیچ چیز کش نمیشود.
تا کنون، ما فقط نحوه ذخیره کردن درخواستهای fetch
با Data Cache را بررسی کردهایم. اما میتوانیم کارهای بیشتری انجام دهیم.
اگر به مثال قبلی خود درمورد راهنماهای شهری برگردیم، ممکن است بخواهیم دادهها را مستقیماً از پایگاه داده خود استخراج کنیم. برای این کار، میتوانیم از تابع cache
که توسط Next.js ارائه شده است استفاده کنیم. این تابع شبیه به تابع cache
React است، با این تفاوت که به جای Request Memoization، در Data Cache اعمال میشود.
import { getGuides } from "./data" import { cache as unstable_cache } from "next/cache" const getCachedGuides = cache(city => getGuides(city), ["guides-cache-key"]) export default async function Page({ params }) { const guides = await getCachedGuides(params.city) // ... }
البته باید به این نکته توجه داشته باشیم که در حال حاضر، این یک ویژگی آزمایشی بوده و به همین دلیل پیشوند آن با unstable_ میباشد. اما این تنها راه برای ذخیرهسازی درخواستهای non-fetch در Data Cache است.
تابع cache سه پارامتر میگیرد (اما فقط دو پارامتر مورد نیاز است). اولین پارامتر تابعی است که میخواهیم کش کنیم. در مثالی که ما داریم تابعgetGuides
است. پارامتر دوم کلید حافظه کش است. زیرا Next.js برای شناسایی کشها به یک کلید نیاز دارد. این کلید آرایهای از رشتهها است و باید برای هر کش منحصر به فردی که داریم ،یکتا باشد. اگر دو تابع cache
دارای آرایه کلیدی یکسانی باشند که به آنها ارسال شده است، همان درخواست دقیق در نظر گرفته میشوند و در کش یکسان ذخیره میگردند(مشابه درخواست fetch با URL و پارامترهای یکسان).
سومین پارامتر، یک پارامتر گزینهای اختیاری است که در آن میتوانیم مواردی مانند زمان اعتبار سنجی مجدد و برچسبها را تعریف کنیم.
در کدی که ما داریم، نتایج تابعgetGuides
را کش کرده و با کلید ["guides-cache-key"]
در حافظه کش ذخیره میکنیم. این بدان معناست که اگر دو بار getCachedGuides
را با همان شهر فراخوانی کنیم، بار دوم به جای فراخوانی مجدد getGuides
، از دادههای ذخیره شده استفاده میکند.
سومین نوع کش، Full Route Cache است. درک این مورد کمی سادهتر از مفاهیم قبلی است، زیرا نسبت به Data Cache تنظیمات و پیکربندی کمتری دارد.اصلیترین دلیل مفید بودن این Cache این است که به Next.js اجازه میدهد تا به جای اینکه صفحات استاتیک را برای هر درخواست بسازد، آنها را در زمان ساخت(built time) ذخیره کند.
در Next.js، صفحاتی که ما به کلاینتهای خود ارائه میکنیم از HTML و چیزی به نام React Server Component Payload (RSCP) تشکیل شده است. payload شامل دستورالعملهایی برای نحوه کارکرد کلاینت کامپوننتها با سرور کامپوننتهای رندر شده با هدف رندر صفحه میباشد. کاری که Full Route Cache انجام میدهد این است که HTML و RSCP را برای صفحات استاتیک در زمان ساخت(built time) ذخیره میکند.
به عنوان مثال:
import Link from "next/link" async function getBlogList() { const blogPosts = await fetch("https://api.example.com/posts") return await blogPosts.json() } export default async function Page() { const blogData = await getBlogList() return ( <div> <h1>Blog Posts</h1> <ul> {blogData.map(post => ( <li key={post.slug}> <Link href={`/blog/${post.slug}`}> <a>{post.title}</a> </Link> <p>{post.excerpt}</p> </li> ))} </ul> </div> ) }
کدی که در بالا داریم، Page
در زمان زمان ساخت(built time) کش میشود زیرا حاوی هیچ داده پویایی نیست. به طور خاص، HTML و RSCP آن در Full Route Cache ذخیره میشود تا زمانی که کاربر درخواست دسترسی میکند، سریعتر رندر شود. تنها کاری که باعث میشود این HTML و یا RSCP به روز رسانی شود این است که ما برنامه خود را مجدداً deploy کنیم یا این که data cache را، که این صفحه به آن وابسته است به صورت دستی باطل نماییم.
ممکن است اینطور به نظر برسد از آنجایی که ما در حال انجام یک درخواست fetch هستیم دادههای پویا داریم، اما این درخواست fetch توسط Next.js در Data Cache ذخیره میشود، بنابراین این صفحه در واقع استاتیک در نظر گرفته میشود. دادههای پویا دادههایی هستند که در هر درخواست به یک صفحه تغییر میکنند، مانند پارامتر URL پویا، کوکیها، هدرها، پارامترهای جستجو و غیره.
Full Route Cache مانند Data Cache، در سرور ذخیره میشود و در درخواستها و کاربران مختلف باقی میماند، اما برخلاف Data Cache، هر بار که برنامه خود را مجدداً deploy میکنیم، این کش پاک میشود.
انصراف از Full Route Cache به دو صورت انجام میشود.
راه اول انصراف از Data Cache است. اگر دادههایی که برای صفحه fetch میکنیم در Data Cache ذخیره نشده باشد، در Full Route Cache نیز از آنها استفاده نخواهد شد.
راه دوم این است که از دادههای پویا در صفحه خود استفاده کنیم. دادههای پویا شامل مواردی مانند headers
، cookies
یا توابع پویا searchParams
و پارامترهای URL پویا مانند id
در /blog/[id]
هستند.
این Cache آخر کمی منحصر به فرد است زیرا تنها Cacheای میباشد که به جای سرور بر روی کلاینت ذخیره میشود. همچنین اگر به درستی درک نشود، میتواند منبع بسیاری از باگها باشد. Router Cache مسیرهایی که کاربر از آنها بازدید میکند را ذخیره میکند. بنابراین وقتی کاربر به آن مسیرها بازمیگردد، از نسخه ذخیرهشده استفاده میکند و در واقع هیچ درخواستی از سرور صورت نمیگیرد. این روش در مورد سرعت لود صفحه یک مزیت است، اما میتواند مشکلاتی را هم ایجاد کند که در ادامه به آن میپردازیم.
export default async function Page() { const blogData = await getBlogList() return ( <div> <h1>Blog Posts</h1> <ul> {blogData.map(post => ( <li key={post.slug}> <Link href={`/blog/${post.slug}`}> <a>{post.title}</a> </Link> <p>{post.excerpt}</p> </li> ))} </ul> </div> ) }
در کدی که داریم، وقتی کاربر به این صفحه میرود، HTML و RSCP آن در Router Cache ذخیره میشود. به طور مشابه، هنگامی که کاربر به هر یک از مسیرهای /blog/${post.slug}
میرود، آن HTML و RSCP نیز در cache ذخیره میشود. این بدان معناست که اگر کاربر به صفحهای که قبلاً در آن بوده است بازگردد، به جای درخواست از سرور، آن HTML و RSCP را از Router Cache درخواست میکند.
router cache کمی منحصر به فرد است زیرا مدت زمان ذخیره آن به نوع مسیر بستگی دارد. برای مسیرهای استاتیک، کش به مدت ۵ دقیقه ذخیره میشود. اما برای مسیرهای پویا، کش تنها ۳۰ ثانیه ذخیره میگردد. این بدان معنی است که اگر کاربر به یک مسیر استاتیک برود و سپس در عرض ۵ دقیقه به آن بازگردد، از نسخه کش استفاده خواهد کرد. اما اگر بعد از ۵ دقیقه دوباره به آن بازگردد، درخواستی از سرور برای دریافت HTML و RSCP جدید صورت میگیرد. همین مورد در مورد مسیرهای پویا نیز صدق میکند، با این تفاوت که cache به جای ۵ دقیقه فقط ۳۰ ثانیه ذخیره میشود.
این کش همچنین فقط برای session فعلی کاربر ذخیره میشود. به این معنی که اگر کاربر tab را ببندد یا صفحه را رفرش کند، کش پاک میشود.
همچنین میتوانیم با پاک کردن data cache از server action با استفاده از revalidatePath
/revalidateTag
، این cache را مجدداً بهصورت دستی تأیید کنیم. همینطور میتوانیم تابع router.refresh
را که از هوک useRouter
روی کلاینت دریافت میکنیم، فراخوانی نماییم. این کار کلاینت را مجبور میکند تا صفحهای را که در حال حاضر در آن هستیم را دوباره fetch کند.
در بخش قبل دو روش اعتبار سنجی مجدد را مورد بحث قرار دادیم، اما راههای زیادی برای انجام آن وجود دارد.
ما میتوانیم مشابه روشی که این کار را برای Data Cache انجام دادیم، Router Cache را در صورت تقاضا مجدداً اعتبارسنجی کنیم. یعنی این که اعتبار سنجی مجدد Data Cache با استفاده از revalidatePath
یا revalidateTag
نیز باعث اعتبارسنجی مجدد Router Cache میشود.
هیچ راهی برای انصراف از Router Cache وجود ندارد، اما با توجه به روشهای فراوانی که برای اعتبارسنجی مجدد کش وجود دارد، مشکل چندانی نیست.
در این مقاله سعی کردیم تا با انواع مکانیسمهای caching در Next.js آشنا شویم و با درک بهتر رفتار آنها بتوانیم تنظیماتی که برای عملکرد بهتر برنامه لازم است را پیکربندی کنیم.
دیدگاهها:
Faezeeh_rb
بهمن 12, 1402 در 2:18 ب.ظ
خیلی عالی بود.
فرشید انجیلی
بهمن 3, 1402 در 2:28 ب.ظ
بسیار عالی و جامع بود , ممنون