عنوان:

‫بلیزر در دات‌نت ۱۰: خداحافظی با باگ‌های آزاردهنده و سلام به سرعت


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۹/۱۴ ۲۳:۴۱
آدرس: www.dntips.ir
دات‌نت ۱۰ منتشر شده و تغییرات قابل توجهی را برای Blazor به ارمغان آورده است. اگر توسعه‌دهنده Blazor باشید، احتمالا با چالش‌هایی مثل "لرزش صفحه" هنگام لود اولیه یا کندی استارتاپ در نسخه WASM دست‌وبنجه نرم کرده‌اید. خبر خوب این است که مایکروسافت در این نسخه، به‌جای تغییرات بنیادین و گیج‌کننده، روی صیقل دادن لبه‌های زبر و بهبود تجربه کاربری (UX) و تجربه توسعه‌دهنده (DX) تمرکز کرده است. در این مقاله، مهم‌ترین تغییرات Blazor در دات‌نت ۱۰ را بررسی می‌کنیم و یاد می‌گیریم چطور از آن‌ها در پروژه‌های واقعی استفاده کنیم.

۱. حل مشکل "لرزش" داده‌ها (The Flash of Data)
این احتمالا بزرگترین و تأثیرگذارترین تغییر در این نسخه است.

مشکل چه بود؟
اگر از قابلیت Prerendering در Blazor Server (که اکنون پیش‌فرض است) استفاده می‌کردید، حتما متوجه شده‌اید که داده‌ها دو بار لود می‌شوند.
  • بار اول روی سرور (برای ساخت HTML اولیه و سئو).
  • بار دوم روی کلاینت (وقتی تعامل یا Interactivity فعال می‌شود).
نتیجه؟ کاربر یک لحظه داده‌ها را می‌بیند، سپس داده‌ها غیب می‌شوند (یک فلش می‌زند) و دوباره با مقادیر جدید ظاهر می‌شوند. این اتفاق حس بدی به کاربر می‌دهد، انگار که یک روح صفحه شما را تسخیر کرده است!.

راه حل: ویژگی[PersistentState]
در دات‌نت ۱۰، ویژگی (Attribute) جدیدی به نام [PersistentState] معرفی شده است. این ویژگی به Blazor می‌گوید: "داده‌ای که در بار اول (روی سرور) گرفتی را دور نریز! آن را سریالایز کن و به کلاینت بفرست تا دوباره از همان استفاده کند".

نحوه استفاده:
کافیست پراپرتی مورد نظر را با این ویژگی نشانه گذاری کنید:
[PersistentState]
public List<WeatherForecast>? Forecasts { get; set; }

protected override async Task OnInitializedAsync()
{
    // اگر داده‌ها از قبل موجود باشند، دوباره درخواست نمی‌زند
    if (Forecasts is null)
    {
        Forecasts = await GetForecastAsync();
    }
}
با این کار، داده‌ها در HTML جاسازی شده و در رندر دوم بازیابی می‌شوند. دیگر نه لرزشی وجود دارد و نه درخواست اضافه به دیتابیس.

کاربرد مهم دوم: حفظ وضعیت هنگام قطع اینترنت
این ویژگی فقط برای Prerendering نیست. تصور کنید کاربر در حال فیلتر کردن یک گرید است و اینترنتش قطع می‌شود. وقتی دوباره وصل می‌شود (Reconnect)، معمولاً تمام فیلترها می‌پرید چون مدار (Circuit) قبلی از بین رفته بود. اکنون با [PersistentState]، وقتی مدار بسته می‌شود، Blazor وضعیت را در حافظه (یا ردیس) ذخیره می‌کند و به محض اتصال مجدد کاربر، وضعیت (مثلاً ترتیب سورت جدول) را برمی‌گرداند.

۲. انقلاب در سرعت Blazor WASM
نسخه WebAssembly (WASM) بلیزر همیشه از مشکل "حجم بالا" و "لود اولیه کند" رنج می‌برد. در دات‌نت ۱۰، مایکروسافت معماری لودینگ را بازطراحی کرده است.

کاهش حجم و فشرده‌سازی هوشمند
اسکریپت blazor.web.js و فایل‌های DLL اکنون به صورت خودکار با الگوریتم Brotli فشرده می‌شوند.
  • حجم blazor.web.js حدود ۷۶٪ کاهش یافته است.
  • فایل‌ها اکنون "Fingerprint" می‌شوند (نام فایل شامل هش محتواست). این یعنی مشکل کش شدن فایل‌های قدیمی توسط مرورگر کاربر برای همیشه حل شده است.
برای فعال‌سازی کامل این قابلیت در پروژه WASM، این خط را به فایل .csproj اضافه کنید:
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>

خداحافظی با لودینگ آبشاری (Waterfall)
قبلاً فایل‌ها نوبت‌به‌نوبت لود می‌شدند (اول JS، بعد Runtime، بعد DLLها). این پروسه زمان‌بر بود.
اکنون کامپوننت جدیدی به نام <ResourcePreloader /> معرفی شده که تمام منابع حیاتی را به صورت موازی (Parallel) لود می‌کند.
همچنین فایل کانفیگ blazor.boot.json که قبلاً یک درخواست شبکه جداگانه بود، حذف شده و اطلاعات آن مستقیماً در فایل JS ادغام شده است تا یک رفت‌وبرگشت (Round-trip) شبکه کمتر شود.

۳. سیستم اعتبارسنجی (Validation) بالغ‌تر می‌شود
یکی از دردهای توسعه‌دهندگان Blazor، اعتبارسنجی فرم‌های پیچیده بود. در دات‌نت ۱۰ دو بهبود عالی داریم:

الف) پشتیبانی از کلاس‌های تودرتو (Nested Types)
قبلاً اگر مدلی داشتید که داخلش یک کلاس دیگر (مثلاً Address داخل User) بود، DataAnnotations روی کلاس داخلی کار نمی‌کرد.
حالا با اضافه کردن builder.Services.AddValidation() در Program.cs و استفاده از ویژگی [ValidatableType] روی کلاس والد، این مشکل حل شده است.

ب) اعتبارسنجی روی کل کلاس
قبلاً ValidationAttribute فقط روی پراپرتی‌ها کار می‌کرد. الان می‌توانید یک اتریبیوت بنویسید که کل آبجکت را بررسی کند.
مثال: تشخیص ربات‌ها (Honeypot). اگر فیلد مخفی پر شده باشد، کل فرم نامعتبر می‌شود:
[NoBot] // اعمال روی کل کلاس
[ValidatableType]
public class ContactForm
{
    public string Name { get; set; }
    public string Honeypot { get; set; } // باید خالی باشد
}

۴. بهبودهای مسیریابی (Routing) و لینک‌ها

صفحه ۴۰۴ اختصاصی و تمیزتر
قبلاً برای نمایش صفحه "یافت نشد"، باید تگ را داخل روتر شلوغ می‌کردیم. الان کافیست آدرس کامپوننت را در ویژگی NotFoundPage صدا بزنید:
<Router AppAssembly="typeof(Program).Assembly" 
        NotFoundPage="typeof(Pages.NotFound)">
    </Router>

هوشمندی درNavLink
کامپوننت NavLink قبلاً اگر در URL کوئری استرینگ وجود داشت (مثلاً ?page=2)، کلاس Active را گم می‌کرد. در دات‌نت ۱۰، به صورت پیش‌فرض کوئری استرینگ‌ها را نادیده می‌گیرد و لینک را فعال نگه می‌دارد.

۵. کنترل بیشتر روی اتصال (Connection)
مایکروسافت APIهای جاوااسکریپتی جدیدی برای کنترل مدار Blazor Server ارائه داده است. شما می‌توانید زمانی که کاربر تب را عوض می‌کند یا صفحه را Minimize می‌کند، اتصال Blazor را Pause کنید تا منابع سرور آزاد شود و وقتی برگشت، آن را Resume کنید.
document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
        Blazor.pauseCircuit(); // توقف برای صرفه‌جویی در منابع
    } else {
        Blazor.resumeCircuit(); // شروع مجدد
    }
});

۶. متریک‌های جدید برای مانیتورینگ
اگر از ابزارهایی مثل .NET Aspire یا Prometheus استفاده می‌کنید، دات‌نت ۱۰ متریک‌های بسیار دقیقی را اضافه کرده است. شما می‌توانید این متریک‌ها را در Program.cs فعال کنید تا دقیقاً ببینید کامپوننت‌ها چقدر زمان می‌برند یا وضعیت مدارهای سرور چگونه است.


نتیجه‌گیری
دات‌نت ۱۰ برای Blazor یک به‌روزرسانی "بلوغ" محسوب می‌شود. با حل مشکل "Prerendering Flash" از طریق PersistentState و کاهش چشمگیر حجم دانلود در WASM، بلیزر اکنون برای اپلیکیشن‌های عمومی (Public-facing) که سئو و سرعت لود در آن‌ها حیاتی است، به یک گزینه کاملاً جدی تبدیل شده است.


مشاهده مطلب اصلی