SSR یا SSG؛ انتخاب رندر با Freshness، Cache و TCO

صفحه محصول با SSG در ۳۰۰ میلی‌ثانیه باز می‌شود، اما قیمت یک ساعت عقب است. تیم آن را SSR می‌کند؛ قیمت تازه می‌شود، ولی در کمپین شبانه API موجودی کند و همه صفحه‌ها ۵۰۳ می‌شوند. سؤال درست «SSR سریع‌تر است یا SSG؟» نیست؛ سؤال این است که هر بخش صفحه چه مقدار تازگی، شخصی‌سازی، تاب‌آوری و هزینه می‌خواهد.

SSR و SSG زمان و محل تولید HTML را تعیین می‌کنند، نه کیفیت محصول را. هر دو می‌توانند سریع یا کند، امن یا آسیب‌پذیر، قابل‌ایندکس یا معیوب باشند. تصمیم خوب باید برای هر Route و Dataset جداگانه نوشته، با Cache و Invalidation کامل و در شبکه و دستگاه واقعی آزموده شود.

اصل انتخاب: تا جایی که Freshness و شخصی‌سازی اجازه می‌دهند، خروجی پایدار و قابل‌کش بسازید؛ بخش واقعاً پویا را در Request یا Client حل کنید؛ سپس Staleness، Failure و هزینه را عمداً مدیریت کنید.

SSR و SSG دقیقاً چه تفاوتی دارند؟

در SSR، HTML معمولاً هنگام درخواست یا روی Server/Edge تولید می‌شود. در SSG یا Prerendering، HTML پیش از درخواست—در Build یا مرحله تولید—ساخته و به‌صورت Artifact منتشر می‌شود. با Cache و Revalidation، مرز این دو کمتر از گذشته مطلق است.

روشزمان تولید HTMLداده در پاسخ اولیهنقطه شکست غالب
SSG/PrerenderBuild یا پیش‌تولیدSnapshot هنگام تولیدBuild، Invalidation یا داده کهنه
SSRهر Request یا Cache missSnapshot زمان درخواستOrigin/API/compute latency و overload
CSRمرورگرShell و سپس APIBundle، دستگاه، شبکه و API Client
Revalidated staticBuild/درخواست/رویدادآخرین Artifact معتبرStale window یا regeneration failure
Hybrid/Partialترکیبی در یک RouteShell پایدار + بخش پویاCache boundary، Hydration و consistency

«Static» به معنی بدون JavaScript نیست و «Server-rendered» هم به معنی بدون Cache نیست. هر دو ممکن است Hydrate شوند و تعامل Client داشته باشند.

Rendering mode را با Hosting mode یکی نگیرید

Edge rendering محل اجرای Server logic را نزدیک‌تر می‌کند؛ یک Rendering mode مستقل نیست. فایل Static نیز ممکن است از CDN بیاید و SSR می‌تواند پشت CDN Cache شود. همچنین Server Components، Streaming، Islands و Partial prerendering مرز تولید و تعامل را ریزتر می‌کنند.

  • Render: HTML کجا و چه زمانی ساخته می‌شود؟
  • Cache: چه Artifact/Dataی با چه Key و مدتی نگه داشته می‌شود؟
  • Deploy: کد یا فایل در Origin، Serverless یا Edge اجرا/توزیع می‌شود؟
  • Hydrate: چه مقدار JavaScript برای تعامل به مرورگر می‌رسد؟

این چهار تصمیم به هم مرتبط‌اند، اما معادل نیستند. Nuxt نیز Edge-side rendering را بیشتر Deployment target می‌داند و Route rules را برای Hybrid rendering عرضه می‌کند؛ نام قابلیت‌ها میان Frameworkها و نسخه‌ها فرق دارد.

تصمیم را برای Route بنویسید، نه برای کل پروژه

یک سایت واحد می‌تواند خانه Static، صفحه خبر Revalidated، محصول Hybrid، Checkout SSR و Dashboard خصوصی CSR داشته باشد. Route Contract پیشنهادی:

Route: /product/:slug
Audience/Search: public + indexable
Data: description, price, stock, seller, reviews
Freshness: description 24h; price 5m; stock at checkout real-time
Personalization: city/shipping after user context
Initial HTML: identity, description, honest price state, links
Cache key: locale + currency; NOT user id
Invalidation: CMS event + price event + manual purge
Failure: last-known description; fail-closed purchase if stock unknown
SLO: TTFB/LCP/error/staleness/checkout correctness
Render: static shell + revalidated product + dynamic checkout
Owner/Rollback: Catalog Platform / prior artifact

اگر Contract فقط «Next.js با ISR» نوشته باشد، تصمیم معماری هنوز ناقص است.

Freshness budget: داده چقدر می‌تواند کهنه باشد؟

«پویا» واژه دقیقی نیست. قیمت می‌تواند پنج دقیقه Stale باشد، موجودی هنگام خرید نباید حدس زده شود و توضیح محصول شاید یک روز تحمل داشته باشد. برای هر Field بنویسید:

دادهStaleness مجازهنگام اختلالمنبع حقیقت
مقالهساعت/روزآخرین نسخه معتبرCMS version
قیمت نمایشیطبق سیاست کسب‌وکارزمان به‌روزرسانی یا unavailablePricing service
موجودی خریدنزدیک Real-timeFail closed در CommitInventory reservation
وضعیت سفارشکوتاهRetry/last event با هشدارOrder system
پروفایل شخصیSession/contextLogin/fallback امنIdentity/Profile

Render mode از سخت‌گیرانه‌ترین Field لزوماً تعیین نمی‌شود. می‌توانید بخش پایدار را Cache و Validation حیاتی را در Action نهایی انجام دهید.

SSG فقط Build-time کامل نیست

الگوهای Static مدرن چند شکل دارند:

  • Full build: همه Routeها پیش از Deploy تولید می‌شوند.
  • Popular prebuild: صفحه‌های پرترافیک ساخته و Long tail هنگام اولین درخواست تولید می‌شود.
  • Time-based revalidation: پس از بازه، نسخه تازه تولید می‌شود.
  • Event/on-demand invalidation: تغییر CMS/Product، Cache مربوط را نامعتبر می‌کند.
  • Stale-while-revalidate: نسخه کهنه مجاز سریع سرو و Refresh در پس‌زمینه انجام می‌شود.

Next.js ISR و Route rules در Nuxt نمونه‌های Framework-specific این خانواده‌اند. معنای دقیق Cache، درخواست اول، Background regeneration و Adapter/Platform را از مستند همان نسخه/میزبانی بخوانید؛ «ISR» یک رفتار جهانی یکسان نیست.

Cache بدون Key و Invalidation، طراحی نیست

سرعت SSG و SSR cached از Cache می‌آید. قرارداد Cache حداقل این موارد را دارد:

Artifact: product HTML + payload
Key: route × locale × currency × approved variant
Source versions: CMS#1842 + Price#991 + Catalog#551
Freshness: fresh 5m; stale-if-error 30m for non-transactional view
Invalidation: product.updated, price.changed, publish.rollback
Purge scope: exact route + category/card dependencies
Personal data: forbidden in shared cache
Observability: hit/miss/age/version/regeneration/error
Recovery: serve prior safe artifact or explicit unavailable

TTL تنها پاسخ نیست. تغییر محصول ممکن است صفحه دسته، جستجو، Sitemap، Related card و Schema را نیز تحت‌تأثیر قرار دهد. برای Cache key، Header و Service Worker، راهنمای جامع Cache وب را ببینید.

Invalidation را از Event تا Evidence طراحی کنید

رویداد product.updated باید Idempotent، Versioned و قابل‌تکرار باشد. مسیر ساده:

  1. Source of truth تغییر را Commit می‌کند.
  2. Event قابل‌اعتماد با Entity/version منتشر می‌شود.
  3. Dependency map، Route/Fragmentهای متأثر را پیدا می‌کند.
  4. Cache tag/Artifact نامعتبر و Regeneration اجرا می‌شود.
  5. نسخه عمومی با Marker/Checksum تأیید می‌شود.
  6. Lag، Failure و Dead-letter Alert می‌گیرند.

اگر Event از دست برود، TTL/periodic reconciliation باید راه ترمیم داشته باشد. الگوهای Outbox، Idempotency و DLQ در معماری Event-driven توضیح داده شده‌اند.

Snapshot consistency: صفحه سریع اما متناقض نباشد

Build ممکن است عنوان را از CMS نسخه جدید و قیمت را از Catalog نسخه قدیم بگیرد. SSR هم در چند درخواست موازی دچار همین مسئله می‌شود. Data contract باید Version یا Timestamp منابع، timeout، Retry و سازگاری را ثبت کند.

خطرنمونهکنترل
Mixed snapshotVariant حذف‌شده با قیمت جدیدversion pin/snapshot token
Partial buildصفحه جدید بدون دستهatomic publish/manifest
Out-of-order eventنسخه قدیمی آخر اعمال شودmonotonic version/idempotency
Schema driftUI و JSON-LD قیمت متفاوتsingle render data model

«HTML ساخته شد» Acceptance نیست؛ Business invariants باید پاس شوند.

Performance: TTFB، LCP و INP را جدا ببینید

SSG معمولاً TTFB پایینی می‌دهد، ولی Image بزرگ، Font، JavaScript و Third-party هنوز LCP/INP/CLS را خراب می‌کنند. SSR می‌تواند HTML را سریع Stream کند، اما Data waterfall یا Cold start TTFB را بالا ببرد. Hydration نیز صفحه قابل‌مشاهده‌ای می‌سازد که هنوز به Interaction پاسخ نمی‌دهد.

مرحلهSSG riskSSR riskشاهد
Server/EdgeCache miss/regenerationcompute/API/cold startserver timing, trace
NetworkPayload/asset بزرگHTML stream/asset بزرگwaterfall, transfer
RenderHero/Font/CLSstream order/late CSSLCP/CLS attribution
InteractHydration/third-partyHydration/duplicate workINP/long task/RUM

web.dev هشدار می‌دهد Full hydration می‌تواند با وجود FCP بهتر، TBT و INP را بدتر کند. نتیجه را با Field data و دستگاه میان‌رده بسنجید؛ راهنمای Core Web Vitals و RUM مرز Lab و Field را روشن می‌کند.

SSR برای Dashboard شخصی الزام سئو نیست

صفحه خصوصی که نباید Index شود، صرفاً برای SEO به SSR نیاز ندارد. SSR ممکن است برای First view، اشتراک UI یا Security boundary مفید باشد؛ CSR هم می‌تواند برای Back-office مناسب باشد. مهم‌تر:

  • داده شخصی در Cache مشترک نرود؛
  • Cache key به Cookie/User اشتباه وابسته نشود؛
  • HTML شخصی در CDN عمومی ذخیره نشود؛
  • Authorization در Server action/API دوباره کنترل شود؛
  • Logout و Back/Forward داده قبلی را نشت ندهند.

امنیت: SSG سطح حمله را حذف نمی‌کند، جابه‌جا می‌کند

نبود Database query در Request عمومی می‌تواند ریسک Runtime را کم کند؛ اما Build pipeline، CMS token، Dependency، CI runner، CDN، Third-party script، فرم/API و Artifact integrity باقی‌اند. SSR نیز Secret isolation، Injection، SSRF، Cache poisoning و Dependency failure دارد.

سطحSSGSSR
BuildCMS/CI secret و supply chain حیاتیBuild + runtime dependency
RuntimeCDN/form/client/APIserver/API/cache/auth
Data leakSecret در Bundle/ArtifactShared cache/personalized HTML/log
RecoveryArtifact rollback سریع اگر سالمApp/config/data rollback هماهنگ

«Static پس امن است» یک Anti-pattern است. Threat model و Evidence لازم‌اند.

Reliability: Failure mode هر روش متفاوت است

SSG می‌تواند هنگام خرابی CMS همچنان آخرین Artifact را سرو کند؛ اما اگر Build ناقص را Atomic منتشر نکنید، کل سایت ناسازگار می‌شود. SSR داده تازه دارد؛ ولی هر Dependency به مسیر درخواست وارد می‌شود.

FailureStatic/RevalidatedSSRراه‌حل
CMS downآخرین ArtifactRequest failure/timeoutcache/fallback/circuit breaker
Build failنسخه جدید منتشر نشودممکن است بی‌اثر باشدatomic manifest + keep prior
Invalidation lostStale طولانیCache-dependentreconciliation + age alert
Traffic spikeCDN مناسب، regeneration stampede ممکنorigin overloadrequest coalescing/rate/capacity

Availability را با Freshness و Correctness با هم بسنجید؛ صفحه همیشه ۲۰۰ اما دارای قیمت غلط، Reliable نیست.

مقیاس‌پذیری: تعداد Route تنها عامل نیست

یک میلیون URL الزاماً Full build را ناممکن نمی‌کند و ده هزار صفحه الزاماً آسان نیست. Driverها:

  • تعداد URL × نرخ تغییر × Fan-out وابستگی؛
  • زمان و هزینه Fetch/Transform/Image در Build؛
  • تعداد Locale/Variant و اندازه Artifact؛
  • Cache hit ratio و Long-tail traffic؛
  • Concurrency، quota و Deploy window؛
  • Regeneration stampede و Purge limit.

Popular prebuild + on-demand generation + event invalidation اغلب از ساخت کامل بهتر است. برای Quota، Peak/Failure و Economics، راهنمای مقیاس‌پذیری پلتفرم را ببینید.

TCO: Compute تنها هزینه نیست

هزینهSSG/RevalidatedSSR
ComputeBuild/regenerationRequest/cold start
Storage/CDNArtifact/payload زیادCache و egress
Engineeringdependency/invalidation/build opsruntime/cache/capacity ops
Incidentstale/partial publishoutage/latency/cache leak
Vendorbuild minute/purge/functionfunction/edge/observability

Cost per page build یا Cost per request را با Incident، Human on-call و Vendor lock-in جمع کنید. ارزان‌ترین Benchmark، لزوماً ارزان‌ترین سیستم سالانه نیست.

سئو: HTML کامل شرط مفید است، تضمین رتبه نیست

SSR و SSG هر دو می‌توانند محتوای اصلی را در پاسخ اولیه قرار دهند و وابستگی Crawler به JavaScript را کم کنند. اما SEO به URL، Status، Canonical، Robots، لینک، Sitemap، محتوای مفید، Schema و Performance هم وابسته است. صفحه Static با Canonical اشتباه یا ۴۰۴ نرم، «SEO عالی» نیست.

گوگل Server-side یا pre-rendering را ایده خوبی می‌داند، اما Dynamic rendering مخصوص Bot را راه‌حل بلندمدت توصیه نمی‌کند. برای Raw/Rendered diff، History API و Soft ۴۰۴، راهنمای سئوی JavaScript Intent تخصصی مکمل است.

Build pipeline را یک سامانه Production بدانید

SSG Build یک Script جانبی نیست؛ بخشی از Serving path است. حداقل Gateها:

Source snapshot/version pinned
Schema/content/route validation passed
Required URLs and redirects emitted
No secret/PII in client artifact
Link/canonical/robots/status fixtures passed
Asset and bundle budgets passed
Atomic manifest ready
Canary deploy and smoke journeys passed
Previous artifact retained for rollback
Post-deploy URL/version/freshness verified

برای Artifact، Promotion، Canary و Rollback، راهنمای CI/CD جزئیات بیشتری دارد.

Headless CMS بدون Publish contract، Freshness نمی‌دهد

CMS باید Draft/Preview، Scheduled publish، Version، Webhook retry، Locale، Relation و Unpublish را مشخص کند. Preview نباید Artifact عمومی یا Cache را آلوده کند. انتشار باید Entityهای وابسته را invalidate و نتیجه عمومی را تأیید کند.

اگر Editor انتظار انتشار ۳۰ثانیه‌ای دارد ولی Build دو ساعت طول می‌کشد، مشکل «کندی CMS» نیست؛ Operating contract غلط است. برای Content model و Preview/Rendering/Exit، راهنمای Headless CMS را ببینید.

Framework را پس از معماری انتخاب کنید

Next.js، Nuxt، Astro، SvelteKit، Gatsby، Hugo و دیگر ابزارها Capabilityهای متفاوت و متغیری دارند. Checklist بهتر از فهرست محبوبیت است:

  • Static، dynamic، streaming و partial behavior در نسخه فعلی؛
  • Time/event/tag revalidation و Failure semantics؛
  • Self-host/adapter/CDN portability؛
  • Cache header/key/purge visibility؛
  • Preview، local development و production parity؛
  • Observability، artifact export و rollback؛
  • Bundle/Hydration controls و accessibility؛
  • Pricing/quota/lock-in و Exit drill.

Feature در Roadmap یا Blog را قابلیت Production فرض نکنید؛ PoC را روی Adapter و Hosting واقعی اجرا کنید.

چهار سناریوی انتخاب

مجله و Documentation

Static/Revalidated معمولاً نقطه شروع خوبی است. Popular routes پیش‌ساخته، Long tail on-demand، Publish event برای Invalidation و آخرین Artifact هنگام CMS outage. جستجوی داخلی و Comment می‌توانند سرویس جدا باشند. Acceptance شامل انتشار، Unpublish، Redirect و Sitemap است.

سایت خبری

صفحه مقاله می‌تواند event-revalidated باشد؛ Home/Live feed Freshness کوتاه‌تر یا SSR cached می‌خواهد. Breaking news باید Purge و verification سریع داشته باشد. Scheduled publish، Correction و Traffic spike از اول تست شوند.

فروشگاه ایرانی

شرح، تصویر و Category قابل‌کش‌اند؛ قیمت/موجودی Budget جدا دارند و Checkout دوباره Validate می‌کند. شهر، هزینه ارسال و Login به Shared HTML نشت نمی‌کنند. UI، Schema، Feed و Order truth Reconcile می‌شوند؛ وابستگی درگاه یا Catalog خارجی fallback دارد.

SaaS و Dashboard

Marketing/docs عمومی Static یا SSR cached؛ Dashboard خصوصی CSR/SSR براساس UX و Security، نه SEO. Shell می‌تواند Cache شود ولی Data شخصی نه. Permission در API/Server action enforce و Session expiry/Back navigation تست می‌شود.

شرایط ایران را در معماری دخیل کنید

Latency فقط فاصله جغرافیایی نیست. ISP/mobile operator، CDN و Origin، DNS، دسترسی API خارجی، نرخ ارز، محدودیت پرداخت Vendor و کیفیت Android/WebView در نتیجه اثر دارند.

  • SSR Origin خارج از دسترس یا پرLatency می‌تواند همه Routeها را هم‌زمان مختل کند.
  • Static artifact داخلی/چندمبدأ تاب‌آوری می‌دهد، اما Invalidation باید هماهنگ باشد.
  • Font/Analytics/CAPTCHA/Image optimizer خارجی fallback و timeout می‌خواهند.
  • تومان/ریال، تاریخ شمسی/میلادی، RTL/Bidi و Locale باید در Cache key و Snapshot آزموده شوند.
  • Probe از چند اپراتور داخل و خارج، Cold/warm cache و دستگاه میان‌رده لازم است.

مهاجرت را Route-by-Route انجام دهید

بازنویسی کامل معماری قبل از Evidence، ریسک بالایی دارد. یک Vertical slice نماینده انتخاب کنید:

  1. Baseline Field/Server/Cost/Freshness/Incident ثبت شود.
  2. Route contract و Hard gate تصویب شود.
  3. نسخه جدید در Shadow یا Host آزمایشی با Production data safe اجرا شود.
  4. Canary درصدی با URL/SEO parity و Business journey آغاز شود.
  5. Cache age، stale، error، LCP/INP و Outcome مقایسه شوند.
  6. Scale/Hold/Rollback براساس Gate انجام شود.

برای Bundle، CPU، Memory و Security سمت Client، راهنمای Performance و Security اپ JavaScript را در Acceptance قرار دهید.

Scorecard تصمیم SSR یا SSG

عاملگرایش Static/Revalidatedگرایش SSR/Request
Freshnessثانیه/دقیقه/ساعت قابل‌تحملدر هر Request لازم
Personalizationکم یا Client fragmentHTML وابسته به Request با Cache امن
Trafficبالا/نامنظم با Cache hit خوبقابل‌ظرفیت‌گذاری و Cache
Dependencyمی‌توان Snapshot گرفتباید Live query شود
Failure preferenceآخرین نسخه معتبر بهتر از خطاستداده تازه/Unavailable بهتر از Stale است
Update fan-outکم یا Invalidation کنترل‌شدهبسیار زیاد/غیرقابل‌پیش‌بینی
OperationsBuild/artifact expertiseruntime/capacity expertise
تصمیم نهایی: اگر یک Route در دو ستون امتیاز دارد، Hybrid طبیعی است. Static shell با بخش Request، SSR cached با Event invalidation یا Client personalization می‌تواند بهتر از انتخاب خالص باشد—به شرط مرز داده و Cache روشن.

سؤال‌های متداول

آیا SSG همیشه از SSR سریع‌تر است؟

نه. SSG معمولاً TTFB خوبی دارد، اما Asset، تصویر، JavaScript و Hydration می‌توانند LCP/INP را خراب کنند. SSR cached/streamed نیز ممکن است سریع باشد. Field data، Cache state و مسیر کامل کاربر را مقایسه کنید.

آیا فروشگاه اینترنتی حتماً باید SSR باشد؟

خیر. Description و Category می‌توانند Static/Revalidated، قیمت و موجودی با Freshness budget و Checkout با Validation لحظه‌ای باشند. انتخاب Route/Data-specific بهتر از SSR کامل فروشگاه است.

ISR همان SSG با TTL ثابت است؟

ISR نام یک Capability در Next.js است و رفتار دقیقش به Router، نسخه و Hosting وابسته است. خانواده الگو شامل time-based، on-demand و background revalidation است. Failure، stale serving، invalidation و observability را از مستند محیط خود اثبات کنید.

کدام روش برای سئو بهتر است؟

هر دو می‌توانند HTML کامل و سئوی فنی درست بدهند. رتبه تضمین نمی‌شود؛ URL، Status، Canonical، Robots، Link، محتوا، Schema و Performance تعیین‌کننده‌اند. خروجی عمومی را تست کنید، نه نام روش را.

آیا سایت Static امن و بدون سرور است؟

معمولاً Runtime عمومی ساده‌تر می‌شود، اما Build، CMS، CI/CD، Dependency، CDN، Third-party، فرم/API و Secretها باقی‌اند. Attack surface جابه‌جا می‌شود؛ Threat model، Access control، Artifact integrity و Incident response لازم است.

جمع‌بندی

انتخاب SSR یا SSG پاسخ ثابت پروژه نیست؛ قرارداد هر Route و Field است. Freshness، شخصی‌سازی، Cache key، Invalidation، Snapshot، Failure، Hydration، Security، Scale و TCO را بنویسید. سپس با Artifact/Request evidence، Field performance، Business correctness و Rollback آن را در Production ثابت کنید. معماری خوب معمولاً ترکیبی است و مرزهایش عمداً طراحی شده‌اند.

منابع فنی منتخب

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *