برنامه نویسی

SvelteKit Server Load Functions

SvelteKit Server Load Functions

17 دقیقه زمان برای خواندن این مطلب نیاز است.



در دنیای توسعه وب مدرن، سرعت بارگذاری اولیه صفحه و بهینه‌سازی برای موتورهای جستجو (SEO) از اهمیت حیاتی برخوردار هستند. فریمورک‌های Full-Stack مانند SvelteKit با ارائه قابلیت‌هایی مانند رندرینگ سمت سرور (SSR) و توابع بارگذاری (Load Functions) این امکان را فراهم می‌کنند تا داده‌ها پیش از نمایش صفحه به کاربر، در سمت سرور آماده شوند. SvelteKit Server Load Functions قلب این فرآیند هستند. آن‌ها به شما اجازه می‌دهند مستقیماً به پایگاه داده متصل شوید، به فایل‌ها دسترسی داشته باشید یا با APIهای خارجی ارتباط برقرار کنید، بدون اینکه کد حساس شما در معرض دید کلاینت قرار گیرد. در این مقاله جامع از دانا پدیا، به بررسی عمیق SvelteKit Server Load Functions می‌پردازیم. شما با مفاهیم پایه، تفاوت آن با توابع یونیورسال، نحوه دسترسی به پارامترها و کوکی‌ها، مدیریت خطا، بهینه‌سازی کش، استریمینگ داده‌های سنگین و بهترین شیوه‌های عملی آشنا خواهید شد. هدف ما ارائه یک مرجع کامل برای توسعه‌دهندگان SvelteKit در تمام سطوح است.

React Native Performance Optimization

SvelteKit Server Load Functions

Server Load Functions چیست و چرا باید از آن استفاده کنیم؟

در SvelteKit، SvelteKit Server Load Functions توابعی ناهمگام (async) هستند که در فایل‌های +page.server.js (یا +layout.server.js) تعریف می‌شوند و منحصراً در سمت سرور اجرا می‌گردند. این توابع قبل از رندر شدن صفحه، داده‌های مورد نیاز را آماده کرده و به کامپوننت صفحه تزریق می‌کنند. بر خلاف توابع یونیورسال (Universal) که در فایل‌های +page.js تعریف می‌شوند و هم در سرور و هم در کلاینت اجرا می‌شوند، توابع سمت سرور هرگز به مرورگر کاربر ارسال نمی‌شوند. این ویژگی سه مزیت حیاتی دارد:

  1. امنیت: می‌توانید مستقیماً از پایگاه داده کوئری بگیرید، کلیدهای API یا توکن‌های مخفی را بدون نگرانی از لو رفتن آن‌ها در سورس کد فرانت‌اند، درون load استفاده کنید. در حالی که در توابع یونیورسال، هر چیزی که در سرور بارگذاری می‌شود باید قابل سریالایز شدن باشد تا به کلاینت منتقل شود، کد توابع سرور هرگز در معرض دید کاربر قرار نمی‌گیرد. برای مثال، اگر از یک متد داخلی برای اتصال به دیتابیس استفاده می‌کنید، انجام این کار در +page.server.js کاملاً امن است، در حالی که در +page.js این کد در نهایت به مرورگر کاربر راه خواهد یافت.
  2. عملکرد: با کاهش حجم جاوااسکریپت ارسالی به کلاینت و انجام عملیات سنگین روی سرورهای قدرتمند، زمان بارگذاری اولیه صفحه به شدت کاهش می‌یابد. این موضوع مستقیماً روی نرخ تبدیل و تجربه کاربری تأثیر مثبت می‌گذارد و همچنین شانس شما را برای کسب رتبه‌های برتر در گوگل افزایش می‌دهد، زیرا موتورهای جستجو به صفحاتی که محتوای آن‌ها سریع‌تر ارائه می‌شود، اولویت می‌دهند.
  3. دسترسی به محیط سرور: در سرور، به اشیاء قدرتمندی مانند cookies (برای خواندن و نوشتن کوکی‌ها)، setHeaders (برای تنظیم هدرهای HTTP مانند کش)، و locals (برای اشتراک داده بین هوک‌ها و توابع مختلف) دسترسی دارید. همچنین می‌توانید از متد fetch مخصوص SvelteKit استفاده کنید که در سمت سرور از کش داخلی بهره می‌برد و درخواست‌های تکراری را بهینه می‌سازد. علاوه بر این، متدهای جدیدی مانند depends و untrack کنترل دقیق‌تری بر روی invalidate کردن کش و مدیریت وابستگی‌ها در اختیار شما قرار می‌دهند.

به طور خلاصه، SvelteKit Server Load Functions راه حلی استاندارد و کارآمد برای مدیریت داده‌های حساس و بهبود چشمگیر SEO و سرعت اپلیکیشن‌های شما هستند. در مقابل، اگر داده‌های شما از APIهای عمومی دریافت می‌شوند و نیاز به دسترسی به منابع سرور ندارید، توابع یونیورسال گزینه مناسب‌تری خواهند بود. درک تفاوت بین این دو، گام اول برای معماری صحیح برنامه شماست.

آموزش Vim برای برنامه نویسان مدرن

تفاوت کلیدی: Server Load Function در مقابل Universal Load Function

در مسیر یادگیری SvelteKit Server Load Functions، یکی از مهم‌ترین مفاهیمی که باید به آن مسلط شوید، تفاوت آن با توابع یونیورسال است. هر دو در فایل‌های مخصوص به خود در دایرکتوری routes تعریف می‌شوند، اما رفتار و کاربرد آن‌ها تفاوت اساسی دارد.

تفاوت بین Monolith و SOA و Microservices

توابع سرور (Server Load Functions)

  • محل تعریف: فایل‌های +page.server.js یا +layout.server.js.
  • محل اجرا: فقط و فقط در سمت سرور.
  • دسترسی‌ها: به تمام منابع سرور (دیتابیس، فایل‌ها، process.env و …) دسترسی دارد و می‌تواند از اشیاء cookieslocalssetHeaders استفاده کند.
  • کاربرد: بارگذاری داده‌های حساس، عملیات با پایگاه داده، خواندن کوکی‌ها برای احراز هویت، تنظیم هدرهای HTTP (مانند Cache-Control) و هر کاری که نباید در معرض دید کلاینت قرار گیرد.
  • سریالایزیشن: داده‌ای که برمی‌گرداند باید با استفاده از کتابخانه devalue قابل سریالایز شدن باشد. این کتابخانه از انواع داده‌های پیچیده‌تری نسبت به JSON استاندارد پشتیبانی می‌کند، اما همچنان محدودیت‌هایی دارد (مانند عدم پشتیبانی از توابع یا کلاس‌های سفارشی).

Profiling در Node.js برای Performance

توابع یونیورسال (Universal Load Functions)

  • محل تعریف: فایل‌های +page.js یا +layout.js.
  • محل اجرا: هم در سمت سرور (در زمان SSR) و هم در سمت کلاینت (در زمان هیدریشن و ناوبری‌های سمت کلاینت).
  • دسترسی‌ها: به منابع سرور دسترسی ندارد. فقط می‌تواند از APIهای عمومی fetch کند یا به داده‌های درون حافظه دسترسی داشته باشد.
  • کاربرد: بارگذاری داده‌هایی که نیاز به امنیت ندارند و از APIهای عمومی دریافت می‌شوند. همچنین زمانی که نیاز به برگرداندن مقادیری دارید که قابل سریالایز شدن نیستند (مانند یک کامپوننت Svelte).
  • سریالایزیشن: مانند توابع سرور، داده برگشتی باید قابل سریالایز باشد. تنها تفاوت در محل اجراست.

REST API Caching Strategies

استفاده همزمان از هر دو نوع

یک الگوی رایج و قدرتمند، استفاده همزمان از یک تابع سرور و یک تابع یونیورسال در یک صفحه است. فرض کنید می‌خواهید داده‌ای را از دیتابیس سرور بخوانید (مثلاً message: 'some secret')، اما بر اساس آن داده، یک کامپوننت Svelte خاص را به صورت پویا بارگذاری کنید. کامپوننت قابل سریالایز نیست، بنابراین نمی‌تواند از تابع سرور برگردانده شود. در این حالت:

  1. در +page.server.js داده سرور را برگردانید.
  2. در +page.js، از طریق پارامتر data به داده سرور دسترسی پیدا کنید و سپس کامپوننت را شرطی import کنید.

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

قانون طلایی: از توابع سرور برای کارهای «مخفی و امن» و از توابع یونیورسال برای کارهای «عمومی و سریع» استفاده کنید.

React Input Mask Component

آشنایی کامل با شیء RequestEvent و قابلیت‌های آن

قلب تپنده SvelteKit Server Load Functions، شیء RequestEvent است. این شیء به عنوان پارامتر ورودی به تابع load شما پاس داده می‌شود و مجموعه‌ای از متدها و پراپرتی‌های قدرتمند را در اختیارتان قرار می‌دهد که تعامل با درخواست فعلی را ممکن می‌سازد. در اینجا مهم‌ترین آن‌ها را بررسی می‌کنیم:

  • params: آبجکتی از پارامترهای مسیر (Route Parameters). اگر مسیری مانند /blog/[slug] داشته باشید، می‌توانید از طریق params.slug به مقدار آن دسترسی پیدا کنید. این پارامترها بر اساس نام فایل در دایرکتوری routes استخراج می‌شوند.
  • url: یک شیء از کلاس URL مرورگر که اطلاعات کاملی از آدرس درخواست (شامل searchParams برای پارامترهای کوئری) را ارائه می‌دهد. برای مثال، برای دریافت مقدار ?id=5 باید از url.searchParams.get('id') استفاده کنید.
  • fetch: نسخه‌ی ویژه‌ای از Fetch API استاندارد که دو مزیت اصلی دارد: اولاً در سمت سرور، درخواست‌های هم‌مسیر (به همان اپلیکیشن) با استفاده از کش داخلی SvelteKit بهینه می‌شوند و از رفتن به شبکه جلوگیری می‌شود. ثانیاً، در سمت کلاینت، در ناوبری‌های سمت کلاینت، این fetch باعث می‌شود درخواست از طریق سرور پراکسی شود و از بروز مشکلات CORS جلوگیری کند.
  • cookies: APIای برای خواندن، نوشتن و حذف کوکی‌ها. این قابلیت فقط در توابع سرور در دسترس است و کاربرد گسترده‌ای در مدیریت نشست کاربر و احراز هویت دارد. برای مثال، با cookies.get('session_id') می‌توانید توکن جلسه را بخوانید و با cookies.set(...) آن را تنظیم کنید.
  • locals: یک شیء خالی که می‌توانید داده‌های دلخواه خود را در آن قرار دهید. معمولاً در فایل hooks.server.js و در تابع handle مقادیری (مثل اطلاعات کاربر جاری) را در locals ذخیره می‌کنید تا بعداً در توابع load به آن‌ها دسترسی داشته باشید. این یک مکانیسم عالی برای اشتراک اطلاعات در طول چرخه عمر یک درخواست است.
  • setHeaders: تابعی برای تنظیم هدرهای HTTP خروجی. شاید رایج‌ترین کاربرد آن، تنظیم هدر Cache-Control برای کش کردن پاسخ‌های API و صفحات استاتیک به منظور بهبود عملکرد است.
  • depends: تابعی که برای اعلام وابستگی داده‌ها استفاده می‌شود. با فراخوانی depends('custom:key') به SvelteKit اعلام می‌کنید که داده برگشتی به آن کلید خاص وابسته است. سپس در سمت کلاینت، می‌توانید با استفاده از invalidate('custom:key') از ماژول $app/navigation، این تابع load را مجبور به اجرای مجدد و به‌روزرسانی داده‌ها کنید.
  • untrack: تابعی که برای نادیده گرفتن ردیابی وابستگی‌ها استفاده می‌شود. در برخی سناریوها، ممکن است بخشی از کد داخل load به تغییرات URL وابسته نباشد. با قرار دادن آن کد درون untrack، از رندر مجدد غیرضروری تابع load جلوگیری می‌کنید.

تسلط بر این ابزارها، شما را به یک توسعه‌دهنده حرفه‌ای SvelteKit تبدیل خواهد کرد.

Web Accessibility (a11y) Standards

استریمینگ (Streaming) داده‌های غیرضروری با Promises تو در تو

یکی از پیشرفته‌ترین و کاربردی‌ترین قابلیت‌های SvelteKit Server Load Functions، استریمینگ داده‌ها است. در نسخه‌های اولیه SvelteKit، تابع load باید منتظر می‌ماند تا همه داده‌ها (چه سریع و چه کند) به طور کامل بارگذاری شوند، سپس صفحه را رندر می‌کرد. اگر یکی از درخواست‌های API شما چند ثانیه طول می‌کشید، کاربر یک صفحه خالی یا لودینگ می‌دید تا همه چیز آماده شود. این تجربه چندان جالبی نبود. خوشبختانه، از نسخه 1.8 به بعد، استریمینگ به طور پیش‌فرض پشتیبانی می‌شود.

GraphQL در لاراول با Lighthouse

مکانیزم استریمینگ چگونه کار می‌کند؟

به سادگی، شما می‌توانید از توابع load خود یک Promise تو در تو (Nested Promise) برگردانید. SvelteKit هوشمندانه تشخیص می‌دهد که این Promise در سطح اصلی نیست و بنابراین منتظر آن نمی‌ماند. در عوض، رندر اولیه صفحه را با داده‌های سریع آغاز می‌کند و پس از resolved شدن Promise کند، نتیجه آن را از طریق استریم به مرورگر ارسال می‌کند.

پردازش موازی در Node.js با Worker Threads

مثال عملی: صفحه وبلاگ

فرض کنید صفحه نمایش یک پست وبلاگ را دارید. محتوای اصلی پست از پایگاه داده سریع بارگذاری می‌شود، اما بخش «نظرات کاربران» کند است (شاید یک API خارجی). بدون استریمینگ، کاربر تا چند ثانیه صبر می‌کند تا نظرات هم برسد.

ts

// src/routes/blog/[slug]/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params }) => {
    // این درخواست سریع است و در سطح اصلی return قرار دارد
    const post = await getPostFromDatabase(params.slug);

    return {
        post: post,
        streamed: {
            // این Promise به صورت تو در تو برگردانده می‌شود و باعث تاخیر در رندر نمی‌شود
            comments: loadComments(params.slug)
        }
    };
};

async function loadComments(slug: string) {
    // شبیه‌سازی یک درخواست سنگین و کند
    const response = await fetch(`https://api.example.com/comments/${slug}`);
    return response.json();
}

در کامپوننت صفحه نیز می‌توانید با کمک بلاک {#await} وضعیت بارگذاری این داده‌ها را مدیریت کنید:

svelte

<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
    let { data } = $props();
</script>

<article>
    <h1>{data.post.title}</h1>
    <p>{data.post.content}</p>
</article>

<section>
    <h3>نظرات کاربران</h3>
    {#await data.streamed.comments}
        <p>در حال بارگذاری نظرات...</p>
    {:then comments}
        {#each comments as comment}
            <div>{comment.text}</div>
        {/each}
    {/await}
</section>

در این مثال، کاربر بلافاصله محتوای اصلی پست را مشاهده می‌کند و بخش نظرات با یک انیمیشن لودینگ ساده بعداً نمایش داده می‌شود.

دستور rm در لینوکس با مثال

مدیریت بهینه خطاها و بهبود تجربه کاربری

در فرآیند بارگذاری داده همیشه احتمال خطا وجود دارد. چه شبکه قطع شود، چه پایگاه داده پاسخ ندهد، چه توکن احراز هویت منقضی شده باشد. SvelteKit Server Load Functions مکانیزمی بسیار هوشمندانه برای مدیریت این خطاها ارائه می‌دهد که به شما امکان می‌دهد صفحات خطای زیبا و متمرکزی بسازید.

به محض اینکه در یک تابع load (چه سرور و چه یونیورسال) یک خطا (throw) رخ دهد، جریان عادی متوقف می‌شود. اگر این خطا از نوع @sveltejs/kit باشد، SvelteKit وضعیت HTTP مناسب را تنظیم کرده و نزدیک‌ترین فایل +error.svelte در مسیر جاری را رندر می‌کند. این فایل می‌تواند در سطح ریشه (src/routes/+error.svelte) برای مدیریت سراسری خطاها، یا در سطح یک دایرکتوری خاص برای مدیریت دقیق‌تر خطاها تعریف شود.

برای پرتاب یک خطای حرفه‌ای، SvelteKit دو ابزار اصلی در اختیار شما می‌گذارد:

  1. error: برای پرتاب خطاهای قابل انتظار. این خطا معمولاً وضعیت HTTP 4xx (مثلاً ۴۰۴ برای صفحه پیدا نشد) را به همراه دارد.
  2. redirect: برای هدایت کاربر به مسیری دیگر. در مواردی که کاربر دسترسی ندارد، یا صفحه جابه‌جا شده است، می‌توانید از این ابزار استفاده کنید. هدایت‌ها می‌توانند ۳۰۲ (موقت) یا ۳۰۱ (دائم) باشند.

مثال عملی: صفحه پروفایل کاربر

فرض کنید می‌خواهید صفحه پروفایل کاربر را فقط در صورتی نمایش دهید که کاربر لاگین باشد.

ts

// src/routes/profile/+page.server.ts
import { redirect, error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ cookies, locals }) => {
    // 1. چک کردن توکن در کوکی‌ها یا locals
    const sessionToken = cookies.get('session_id');
    if (!sessionToken) {
        // هدایت به صفحه لاگین
        throw redirect(302, '/login');
    }

    try {
        // 2. واکشی اطلاعات کاربر از دیتابیس
        const user = await db.getUserBySession(sessionToken);
        if (!user) {
            // کاربر در دیتابیس یافت نشد (احتمالاً سشن جعلی است)
            throw error(401, 'جلسه نامعتبر، لطفاً دوباره وارد شوید.');
        }
        return { user };
    } catch (err) {
        // 3. مدیریت خطای پیش‌بینی نشده
        console.error('Database error:', err);
        throw error(500, 'خطای داخلی سرور رخ داده است.');
    }
};

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

اصول پیشرفته: دسترسی به داده والد (Parent) و جلوگیری از Waterfall

همان‌طور که لایه‌های Layout در SvelteKit می‌توانند تو در تو باشند، SvelteKit Server Load Functions نیز قابلیت ارث‌بری از والد را دارند. به این معنی که یک load در یک صفحه یا layout فرزند می‌تواند به داده‌هایی که توسط load والد (layout بالادستی) برگردانده شده‌اند دسترسی پیدا کند. این کار توسط تابع parent که در پارامترهای load در دسترس است، انجام می‌شود.

قوانین مهم استفاده از parent:

  1. یک تابع load یونیورسال (+page.js) می‌تواند از داده‌های load سرور والد (+layout.server.js) استفاده کند.
  2. اما عکس این قضیه صادق نیست: یک تابع load سرور (+page.server.jsنمی‌تواند از داده‌های load یونیورسال والد (+layout.js) استفاده کند. داده‌های یونیورسال والد فقط در اختیار توابع یونیورسال فرزند قرار می‌گیرد.

چالش Waterfall و راه حل

بزرگترین خطر در استفاده از await parent() ایجاد Waterfall (آبشاری) در درخواست‌ها است. یعنی تابع منتظر می‌ماند تا داده والد برسد و سپس شروع به دریافت داده‌های خود می‌کند. اگر این کار چندین لایه عمیق تکرار شود، زمان بارگذاری صفحه به شدت افزایش می‌یابد.

راه حل: سعی کنید داده‌هایی که به والد وابسته نیستند را به صورت موازی (Parallel) و قبل از await parent() واکشی کنید. می‌توانید از Promise.all یا ساختارهای مشابه استفاده کنید.

مثال:

ts

// src/routes/dashboard/+page.server.ts
export const load = async ({ parent, fetch }) => {
    // 1. شروع واکشی داده‌های مستقل (بدون منتظر ماندن برای والد)
    const independentDataPromise = fetch('/api/notifications');

    // 2. دریافت داده والد (مثلاً اطلاعات کاربر از layout بالادستی)
    const { user } = await parent();

    // 3. واکشی داده‌ای که به user وابسته است
    const userSpecificData = await fetch(`/api/dashboard/${user.id}`);

    // 4. منتظر ماندن برای نتیجه درخواست مستقل
    const independentData = await independentDataPromise;

    return {
        user,
        dashboard: await userSpecificData.json(),
        notifications: await independentData.json()
    };
};

در این الگو، به جای اینکه ۲ ثانیه منتظر parent باشید و بعد ۱ ثانیه دیگر برای notifications، هر دو به صورت موازی شروع شده‌اند. این کار زمان کلی بارگذاری صفحه را به حداکثر زمان بین آن‌ها (یعنی ۲ ثانیه) کاهش می‌دهد.

بهینه‌سازی و کاهش بار اضافی (Over-fetching) با داده‌های متمرکز

یکی از چالش‌های بزرگ در معماری کامپوننت‌ها، وابستگی بیش از حد یک کامپوننت به یک تابع load خاص است. فرض کنید کامپوننت CommentSection را نوشته‌اید. حالا اگر این کامپوننت در صفحه اصلی وبلاگ، صفحه پست‌ها و صفحه داشبورد استفاده شود، مجبورید در هر یک از این توابع load کد تکراری برای fetch کردن نظرات بنویسید.

راهکار: Layout سراسری با داده متمرکز

می‌توانید داده‌های پرتکرار را در یک +layout.server.js سطح بالا قرار دهید تا در همه صفحات در دسترس باشد. برای مثال، اطلاعات کاربر لاگین شده یا لیست دسته‌بندی‌ها.

ts

// src/routes/+layout.server.ts
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals }) => {
    // فرض کنید اطلاعات کاربر در locals ذخیره شده است
    const user = locals.user;
    const categories = await db.getCategories();

    return { user, categories };
};

این داده‌ها به صورت سراسری در تمام صفحات از طریق data در +layout.svelte یا از طریق parent() در توابع load فرزند در دسترس خواهند بود.

این الگو نه تنها کد تکراری را حذف می‌کند (کاهش Over-fetching منطقی)، بلکه امنیت را نیز افزایش می‌دهد، زیرا تمام عملیات حساس در یک مکان متمرکز شده و مدیریت آن آسان‌تر است. با این حال، باید مراقب باشید که حجم داده‌های سراسری زیاد نشود، زیرا این داده‌ها به تمام صفحات ارسال خواهند شد.

جمع‌بندی و بهترین شیوه‌های نهایی

در این مقاله از دانا پدیا به بررسی عمیق SvelteKit Server Load Functions پرداختیم. این توابع ابزاری قدرتمند برای ساخت اپلیکیشن‌های سریع، امن و سازگار با موتورهای جستجو هستند. برای استفاده بهینه از آن‌ها، نکات زیر را به خاطر بسپارید:

  • امنیت: اطلاعات حساس (کلیدهای API، اطلاعات احراز هویت، ارتباط مستقیم با دیتابیس) را همیشه در +page.server.js نگه دارید و از +page.js برای عملیات عمومی استفاده کنید.
  • سرعت: برای داده‌هایی که زمان گیر هستند، از استریمینگ و Promises تو در تو در توابع سرور استفاده کنید تا کاربر بلافاصله محتوای اصلی را ببیند.
  • ساختار: برای جلوگیری از Waterfall، وابستگی‌های داده را بشناسید و درخواست‌های مستقل را به صورت موازی انجام دهید.
  • بهینه‌سازی: از هدرهای Cache-Control با استفاده از setHeaders برای کش کردن داده‌های استاتیک و کاهش بار سرور استفاده کنید. همچنین از ابزار depends برای invalidate کردن هدفمند کش در سمت کلاینت بهره ببرید.
  • نظارت: برای درک بهتر عملکرد و رفع گلوگاه‌های احتمالی، از ابزارهای Observability مانند OpenTelemetry که SvelteKit از نسخه‌های اخیر از آن پشتیبانی می‌کند، استفاده کنید. با این ابزارها می‌توانید زمان اجرای هر تابع load را اندازه‌گیری کنید.
SvelteKit Server Load Functions

سوالات متداول (FAQ)

۱. تفاوت اصلی بین load در +page.js و +page.server.js چیست؟
+page.server.js فقط در سمت سرور اجرا می‌شود و به منابعی مانند دیتابیس و کوکی‌ها دسترسی دارد. +page.js هم در سرور (در SSR) و هم در کلاینت اجرا می‌شود و عمدتاً برای بارگذاری داده‌های عمومی از APIها استفاده می‌شود.

۲. آیا می‌توانم همزمان از +page.js و +page.server.js در یک مسیر استفاده کنم؟
بله، کاملاً. داده برگشتی از +page.server.js از طریق پارامتر data در +page.js در دسترس است. این الگو برای ترکیب داده‌های امن سرور با مقادیر غیرقابل سریالایز (مثل کامپوننت‌ها) کاربرد دارد.

۳. چگونه می‌توانم بعد از عملیات خاصی (مثل ثبت نظر جدید) داده‌های صفحه را به‌روز کنم؟
در تابع سرور خود از depends('custom:key') استفاده کنید و در سمت کلاینت پس از POST درخواست، invalidate('custom:key') را فراخوانی کنید تا SvelteKit توابع load وابسته را مجدداً اجرا کند.

۴. آیا SvelteKit Server Load Functions در حالت Static Site Generation (SSG) هم کار می‌کنند؟
خیر. در حالت Prerender (SSG)، خروجی loadها در زمان build به صورت فایل‌های HTML استاتیک ذخیره می‌شوند و دیگر در سرور اجرا نمی‌شوند. منطقی که نیاز به داده‌های لحظه‌ای دارد باید در سمت کلاینت اجرا شود.

۵. بهترین روش برای جلوگیری از اشتباهات تایپی در دسترسی به params و data چیست؟
SvelteKit به صورت خودکار فایل‌های تایپ ($types) را برای شما تولید می‌کند. با Import کردن PageServerLoad یا PageLoad از ./$types، تابع شما به طور کامل Type Safe می‌شود و تمام paramsها به درستی شناسایی می‌شوند.

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