
Sanity CMS: حل چالش Latency و پایداری در ایران با معماری Next.js ISR
مقدمه
در سالهای اخیر، معماری Headless CMS به استاندارد توسعه محصولات دیجیتال مدرن تبدیل شده است. Sanity.io با ارائه Schema-as-Code و GROQ Query Language، انتخاب اول تیمهای مهندسی در جهان است. اما استفاده از آن در کشورهای با محدودیت زیرساختی مانند ایران، چالشهای فنی جدی (Latency بالا و محدودیتهای دسترسی) به همراه دارد.
این مقاله از سری مستندات فنی SENT، برای حل این چالش با استفاده از معماری Next.js ISR و Edge Caching اختصاص دارد. اگر به دنبال راهکارهای معماری مشابه برای پروژه خود هستید، خدمات طراحی سیستمهای Enterprise ما میتواند کمک کند.
بخش اول: تحلیل چالش
۱.۱ ماهیت مسئله
Sanity.io از معماری API-First استفاده میکند. در تستهای ما بر روی یک پروژه سازمانی در ایران، سه چالش اصلی شناسایی شد:
۱. تأخیر شبکه (Network Latency)
به دلیل نبود Edge Location در خاورمیانه و routing نامناسب، میانگین TTFB برای درخواستهای مستقیم API بین ۲۰۰۰ تا ۴۰۰۰ میلیثانیه بود.
۲. قابلیت اطمینان (Reliability)
وابستگی Runtime به API خارجی به معنی آسیبپذیری در برابر اختلالات اینترنت بینالمللی است.
۳. هزینه
برای سایتی با ۵۰۰ هزار بازدید ماهانه، درخواست مستقیم به API، هزینههای Bandwidth غیرمنطقی ایجاد میکند.

۱.۲ راهحلهای ناکارآمد
برخی از رویکردهای رایج که جواب نمیدهند:
Client-Side Fetching: بارگذاری محتوا پس از رندر اولیه که SEO را خراب میکند.Basic Server Caching: همچنان به API calls اولیه با Latency بالا نیاز دارد.
استفاده از VPN: غیرقابلاعتماد و افزایش complexity
بخش دوم: راهحل مهندسی
ما معماری را بر سه اصل بنا کردیم:
Decoupling (جداسازی لایه داده از کاربر)
Edge Caching
Incremental Updates
۲.۱ معماری ISR (Incremental Static Regeneration)
به جای Fetch کردن داده در لحظه درخواست (SSR که کند است)، یا در زمان Build (Static که قدیمی میشود)، از ISR استفاده کردیم.
// pages/posts/[slug].js
export async function getStaticProps({ params }) {
const query = *[_type == "post" && slug.current == $slug][0];
const post = await fetchWithFallback(query, { slug: params.slug });
return {
props: { post },
revalidate: 60, // تلاش برای بهروزرسانی هر ۶۰ ثانیه
};
}مکانیسم کار:
1. کاربر اول محتوای Static را میبیند. (سریع)
2. در Background، Next.js محتوا را از Sanity میگیرد.
3. کاربرِ بعدی، نسخه تازه را دریافت میکند.

۲.۲ لایه امنیتی؛ Reverse Proxy
برای اطمینان از دسترسی پایدار به Sanity API در زمان Build (بهویژه در محیطهای CI/CD داخل ایران)، یک لایه Reverse Proxy شفاف پیادهسازی شد.
ویژگیهای این لایه:
Routing درخواستها از طریق سرور واسط
Retry خودکار با استراتژی Backoff در صورت Timeout
Logging دقیق برای Monitoring سلامت ارتباط.
نکته مهم:
این لایه فقط در Build Time فعال است و هیچ تأثیری بر سرعت کاربر نهایی ندارد. (چون محتوا Static است)
۲.۳ استراتژی Fallback چند لایه
برای تضمین Uptime نزدیک به ۱۰۰٪، یک سیستم caching چند لایه طراحی کردیم:
// lib/sanity-client.js
import NodeCache from 'node-cache';
import fs from 'fs/promises';
const memoryCache = new NodeCache({ stdTTL: 3600 });
export async function fetchWithFallback(query, params) {
const cacheKey = JSON.stringify({ query, params });
try {
// سطح ۱: دریافت مستقیم از Sanity با Timeout
const result = await Promise.race([
sanityClient.fetch(query, params),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), 5000)
)
]);
// ذخیره در Memory و Disk
memoryCache.set(cacheKey, result);
await saveToDisk(cacheKey, result);
return result;
} catch (error) {
console.warn('Sanity fetch failed, using fallback...');
// سطح ۲: Memory Cache
const cached = memoryCache.get(cacheKey);
if (cached) return cached;
// سطح ۳: Disk Cache (آخرین نسخه موفق)
const diskCached = await loadFromDisk(cacheKey);
if (diskCached) return diskCached;
// سطح ۴: Static Fallback (جلوگیری از Crash)
return {
title: 'محتوا در حال بهروزرسانی...',
body: [],
publishedAt: new Date().toISOString()
};
}
}
چهار سطح محافظت:
1. API مستقیم (با Timeout سختگیرانه)
2. Memory Cache (سریعترین)
3. Disk Cache (پایدارترین)
4. Static Fallback (آخرین خط دفاعی)

4. Static Fallback (آخرین خط دفاعی)
۲.۴ بهروزرسانی آنی با Webhooks
برای اینکه تیم محتوا تغییرات را بلافاصله ببیند، از Webhooks استفاده کردیم:
// pages/api/revalidate.js
export default async function handler(req, res) {
const signature = req.headers['sanity-webhook-signature'];
if (!isValidSignature(req.body, signature)) {
return res.status(401).json({ message: 'Invalid signature' });
}
try {
const { _type, slug } = req.body;
await res.revalidate(/${_type}/${slug.current});
return res.json({ revalidated: true });
} catch (err) {
return res.status(500).json({ message: 'Error revalidating' });
}
}
جریان کار:
1. محتوا در Sanity منتشر میشود.
2. Webhook به Next.js ارسال میشود.
3. صفحه مربوط در Background rebuild میشود.
4. کاربران بعدی محتوای تازه را میبینند. (معمولاً < ۵ ثانیه)

بخش سوم: نتایج عملیاتی
پیادهسازی این معماری روی یک پلتفرم e-commerce با ۵۰۰ هزار بازدید ماهانه، نتایج زیر را ثبت کرد:
| شاخص | قبل از اجرا | بعد از معماری SENT | بهبود |
|---|---|---|---|
| TTFB (تهران) | ۲۱۰۰ میلیثانیه | ۸۵ میلیثانیه | ۹۶٪ 🚀 |
| LCP | ۴٫۲ ثانیه | ۱٫۱ ثانیه | ۷۴٪ |
| API Calls (ماهانه) | ۵۰۰,۰۰۰ | ۵۰,۰۰۰ | ۹۰٪ کاهش |
| هزینه زیرساخت | ۱۲۰ میلیون تومان | ۱۷ میلیون تومان | ۸۶٪ صرفهجویی |
| Uptime | ۹۸٫۵٪ | ۹۹٫۹۹٪ | پایدار |

ابزار اندازهگیری:
WebPageTest (سرور تهران) + Vercel Analytics
تأثیر بر کسبوکار
Bounce Rate: کاهش ۳۵٪
Conversion Rate: افزایش ۲۲٪ در صفحات محصول
Support Tickets: حذف کامل تیکتهای "سایت کُند"
نتیجهگیری
استفاده از Sanity CMS در ایران غیرممکن نیست، بلکه نیازمند مهندسی دقیق است. با ترکیب ISR، Reverse Proxy و استراتژی Fallback چند لایه، ما تجربه کاربری جهانی را با زیرساخت محلی ترکیب کردیم.
سه نکته مهم:
1. Latency API را با Static Generation از مسیر حساس حذف کنید.
2. همیشه چند لایه Fallback داشته باشید.
3. از Webhooks برای بهروزرسانی فوری استفاده کنید.
منابع و مراجع
1. [Next.js ISR Documentation](https://nextjs.org/docs/pages/guides/incremental-static-regeneration)
2. [Sanity Webhooks Guide]
(https://www.sanity.io/guides/sanity-webhooks-and-on-demand-revalidation-in-nextjs)
3. [How ISR Works - FreeCodeCamp
(https://www.freecodecamp.org/news/how-incremental-static-regeneration-isr-works-in-nextjs/)
هویت SENT
SENT گروهی از مهندسان نرمافزار است که بر روی طراحی و پیادهسازی سیستمهای Enterprise برای برندهای B2B تمرکز دارد. تخصص ما حل چالشهای معماری پیچیده، یکپارچهسازی سیستمها و ارائه راهحلهای مقیاسپذیر است.