اخبار وب

فریمورک Qwik و مفهوم Resumability

تفاوت Resumability و Hydration، قرارداد component$ و handlerها و نمونه کامل شمارنده در پروژه Qwik؛ بدون وعده زمان تعامل صفر یا مقایسه حجم ساختگی.

1404/11/18 2 دقیقه مطالعه 1,459 بازدید
فریمورک Qwik و مفهوم Resumability

Qwik با Resumability تلاش می‌کند مرورگر بتواند ادامهٔ یک رابط ساخته‌شده در سرور را با کار اولیهٔ کمتری انجام دهد. این هدف با تضمین «زمان تعامل صفر» تفاوت دارد. شبکه، دستگاه، داده و کد هر محصول همچنان بر پاسخ رابط اثر می‌گذارند. مقایسهٔ قبلی این مقاله که یک کیلوبایت Qwik را در برابر بیش از صد و پنجاه کیلوبایت Next.js می‌گذاشت، پروژه و روش اندازه‌گیری مشخصی نداشت و حذف شده است. چنین عددی را نمی‌توان نتیجهٔ عمومی دو معماری دانست.

برای فهم Resumability بهتر است از یک پرسش شروع کنیم: مرورگر پس از دریافت HTML، برای پاسخ به اولین کلیک چه اطلاعاتی لازم دارد؟ باید بداند handler کدام است، به چه Stateی وابسته است و کد لازم از کجا می‌آید. توضیح رسمی Resumability در Qwik مسیر حفظ اطلاعات لازم برای ادامهٔ اجرا را شرح می‌دهد. مزیت معماری زمانی قابل ارزیابی است که این مسیر را در یک جریان واقعی محصول ببینیم.

Hydration و Resumability را دقیق‌تر ببینیم

در بسیاری از رابط‌های رندرشده در سرور، مرورگر برای برقرار کردن رفتار تعاملی، بخشی از منطق کامپوننت‌ها را اجرا می‌کند. این فرایند را معمولاً Hydration می‌نامند. میزان و زمان آن در همهٔ ابزارها یکسان نیست. عبارت «تمام فریمورک‌ها همیشه کل JavaScript را همان ابتدا اجرا می‌کنند» توصیف مناسبی از تنوع روش‌ها نیست. هنگام مقایسه، باید پیکربندی واقعی، بخش‌های تعاملی و راهبرد بارگذاری هر دو گزینه معلوم باشد.

در Resumability، اطلاعات لازم برای ارتباط میان رابط، State و handlerها به شکلی قابل ادامه دادن حفظ می‌شود. Qwik با ابزار build خود کد را به بخش‌هایی تقسیم می‌کند که امکان بارگذاری مستقل داشته باشند. این کار به معنی حذف JavaScript از محصول نیست؛ محل و زمان نیاز به کد تغییر می‌کند. اگر بعد از کلیک، عملیات سنگین اجرا شود، همان عملیات همچنان هزینه دارد. معماری ورود به تعامل و کیفیت منطق تعامل دو مسئولیت جدا هستند.

علامت دلار بخشی از قرارداد کد است

در Qwik نام‌هایی مانند component$ و onClick$ را می‌بینید. این علامت فقط یک سلیقهٔ نام‌گذاری نیست و با مرزهایی که Optimizer بررسی می‌کند ارتباط دارد. معرفی کامپوننت‌های Qwik توضیح می‌دهد چگونه کامپوننت‌ها به بخش‌های قابل بارگذاری تقسیم می‌شوند. خواننده‌ای که از React می‌آید، بهتر است همان ابتدا این قرارداد را ببیند و کد را فقط JSX مشابه با نام‌های متفاوت فرض نکند.

شناخت مرز handler برای انتخاب داده‌ای که آن handler به آن دسترسی دارد لازم است. یک تابع ممکن است به متغیری در بیرون خود اشاره کند، اما در معماری قابل ادامه، شکل این وابستگی اهمیت پیدا می‌کند. انتقال تصادفی شیءهای بزرگ یا منابع وابسته به محیط اجرا می‌تواند مسئله بسازد. قبل از آوردن یک کتابخانهٔ مرورگری به handler، بررسی کنید که چه چیزی باید در سرور وجود داشته باشد و چه چیزی فقط هنگام تعامل لازم است.

نمونهٔ کامل یک شمارنده در پروژهٔ Qwik

مثال زیر یک شمارندهٔ کوچک است و به API، پایگاه داده یا کتابخانهٔ UI نیاز ندارد. برای اجرا، یک محیط Node.js سازگار با نسخهٔ scaffold انتخاب‌شده و npm لازم است. طبق راهنمای رسمی شروع، با npm create qwik@latest پروژه بسازید و گزینهٔ پروژهٔ خالی را انتخاب کنید. مسیر پیشنهادی را مشخص کنید و نصب dependencyها را انجام دهید. خروجی scaffold فایل‌های تنظیم و entryهای لازم را فراهم می‌کند؛ نمونهٔ TSX زیر به‌تنهایی جای آن ساختار نیست.

در پروژهٔ ساخته‌شده، فایل src/routes/index.tsx را با محتوای زیر جایگزین کنید. اگر scaffold نمونهٔ دیگری در این مسیر دارد، همان فایل صفحهٔ اصلی را عوض کنید و فایل تازه‌ای با مسیر حدسی نسازید. کد، ساختار صفحه و CSS خودش را همراه دارد. نام کلاس counter-page در main وجود دارد و selector دکمه‌ها نیز فقط به دکمه‌های همان صفحه اشاره می‌کند. هیچ فایل ظاهری معرفی‌نشده‌ای برای خواندن مثال لازم نیست.

import { component$, useSignal, useStylesScoped$ } from '@builder.io/qwik';

export default component$(() => {
  const count = useSignal(0);
  useStylesScoped$(`
    .counter-page { max-width: 36rem; margin: 2rem auto; padding: 1.5rem; font-family: system-ui; }
    .counter-page button { font: inherit; padding: .6rem 1rem; margin-inline-end: .5rem; cursor: pointer; }
    .counter-page button:focus-visible { outline: 3px solid #2447a8; outline-offset: 3px; }
  `);
  return (
    <main class="counter-page" lang="fa" dir="rtl">
      <h1>شمارنده آموزشی Qwik</h1>
      <p aria-live="polite">تعداد: {count.value}</p>
      <button type="button" onClick$={() => { count.value += 1; }}>افزایش</button>
      <button type="button" onClick$={() => { count.value = 0; }}>بازنشانی</button>
      <p>این مقدار فقط State محلی نمونه است.</p>
    </main>
  );
});

در پوشهٔ پروژه، npm run dev را اجرا کنید و نشانی محلی چاپ‌شده توسط ابزار را باز کنید. در این مثال، افزایش عدد با یک handler مشخص انجام می‌شود و بازنشانی عدد handler جدا دارد. شمارنده ابتدا صفر است؛ این مقدار یک State آموزشی محلی است و بعد از ساخت صفحه از پایگاه داده نمی‌آید. نمونه هیچ ادعایی دربارهٔ حجم bundle یا زمان تعامل اندازه‌گیری‌شده ندارد. برای بازتولید محیط خود، نسخهٔ scaffold و فایل lock را نگه دارید.

Signal را برای دادهٔ همان تعامل انتخاب کنید

useSignal در نمونه، مقدار عددی شمارنده را نگه می‌دارد و count.value در متن نمایش داده می‌شود. افزایش و بازنشانی نیز همان مقدار را تغییر می‌دهند. مرجع State در Qwik ابزارهای نگهداری State را توضیح می‌دهد. برای این مسئلهٔ کوچک، یک شیء پیچیده با چند لایه لازم نیست. شکل State باید با عملیاتی که روی آن انجام می‌شود تناسب داشته باشد تا خوانندهٔ بعدی بتواند رابطهٔ داده و نمایش را دنبال کند.

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

بارگذاری تنبل، هزینه را جابه‌جا می‌کند

اگر کدی هنگام تعامل لازم شود، مسیر دریافت آن بخشی از تجربهٔ همان تعامل خواهد بود. پیش‌دریافت و cache ممکن است کمک کنند، اما نباید فرض کرد هر کاربر همهٔ کد لازم را از قبل دارد. برای یک دکمهٔ کم‌اهمیت و یک اقدام اصلی پرداخت، حساسیت به تأخیر متفاوت است. تصمیم دربارهٔ تقسیم کد باید جریان واقعی کاربر را در نظر بگیرد. کمتر بودن کار اولیه، تنها یکی از معیارهای کیفیت تجربه است.

صفحه‌ای با چند تعامل محدود، از نظر الگوی استفاده با یک ویرایشگر که کاربر پیوسته در آن تایپ می‌کند متفاوت است. در بررسی فریمورک، بخش سخت همان محصول را انتخاب کنید. اگر محصول به نمودار تعاملی یا editor وابسته است، شمارندهٔ ساده دربارهٔ سازگاری آن کتابخانه‌ها چیزی ثابت نمی‌کند. نمونهٔ حاضر برای فهم API و ساختار است. نمونهٔ تصمیم‌گیری باید dependencyها و عملیات واقعی گزینهٔ شما را دربرگیرد.

وابستگی به مرورگر را در محل درست قرار دهید

کدی که در سرور اجرا می‌شود به DOM مرورگر دسترسی ندارد. پس استفاده از window و document باید با مرحلهٔ اجرای مناسب هماهنگ باشد. در مثال هیچ دسترسی مستقیم به DOM لازم نیست؛ JSX و State برای رفتار شمارنده کافی‌اند. وقتی کتابخانه‌ای به DOM نیاز دارد، قبل از نصب آن بررسی کنید که راه‌اندازی و آزاد کردن منبع چگونه انجام می‌شود. کپی کردن نمونهٔ کلاینتی به بدنهٔ کامپوننت ممکن است این تفاوت محیط را پنهان کند.

مرجع Events در Qwik برای قرارداد handlerها و صفحهٔ QRL برای ارجاع به بخش‌های کد مفید است. لازم نیست برای شروع، همهٔ جزئیات داخلی را حفظ کنید. کافی است هنگام انتقال یک تابع یا منبع، بدانید چرا آن وابستگی از مرز بارگذاری عبور می‌کند و آیا شکل آن با سازوکار فریمورک سازگار است. این پرسش از اضافه کردن چند علامت دلار به کد موجود دقیق‌تر است.

مقایسهٔ قابل استفاده برای تیم

اگر تیم می‌خواهد Qwik را کنار گزینه‌ای دیگر بررسی کند، هر دو نمونه باید جریان مشابه داشته باشند. تعداد آیتم‌ها، داده، libraryهای جانبی و وظیفهٔ کاربر را برابر نگه دارید. سپس مشخص کنید چه چیزی را می‌سنجید: دریافت اولیه، اولین تعامل یا تعامل‌های بعدی. ترکیب کردن نتیجهٔ این موقعیت‌ها در یک عدد، تفاوت معماری را مبهم می‌کند. گزارش باید شرایط دستگاه و شبکه را نیز ثبت کند تا همکار بتواند محدودهٔ نتیجه را بفهمد.

هزینهٔ یادگیری، سازگاری ابزارها و استقرار نیز در تصمیم جا دارند. برای ادامهٔ بحث، راهنمای خواندن آمار فریمورک‌ها توضیح می‌دهد چرا محبوبیت عمومی پاسخ همهٔ پرسش‌های پروژه نیست. بعد از فهم نمونهٔ شمارنده، یک بخش محدود از محصول خود را انتخاب کنید و نقاط ناشناختهٔ آن را بنویسید. این مسیر، Qwik را به گزینه‌ای قابل بررسی تبدیل می‌کند، بدون اینکه از یک مفهوم معماری وعدهٔ عملکرد مطلق بسازد.

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!