تفاعل Blazor في .NET 9 و.NET 10: دليل كامل
إذا كنت تقوم بإنشاء تطبيقات الويب باستخدام Blazor على مدى السنوات القليلة الماضية، فأنت تعلم أن إطار العمل قد قطع شوطًا طويلًا. ما بدأ كاختيار بين Blazor Server وBlazor WebAssembly تطور إلى نموذج عرض موحد ومرن يتيح لك اختيار استراتيجية التفاعل الصحيحة لكل مكون في تطبيقك.
مع .NET 8 حصلنا على التحول الأساسي — تقديم أوضاع العرض والعرض الثابت من جانب الخادم (SSR) كوضع افتراضي. والآن، يعتمد الإصداران .NET 9 و.NET 10 على هذا الأساس من خلال التحسينات التي تجعل تجربة المطور أكثر سلاسة وتجربة المستخدم النهائي أسرع.
في هذا المنشور، أريد أن أطلعكم على الصورة الكاملة لتفاعل Blazor كما هي اليوم: كيف تعمل أوضاع العرض، وما يجلبه تدفق SSR إلى الطاولة، وكيف يغير التنقل المحسن والتعامل مع النماذج اللعبة، وما هو الجديد في أحدث الإصدارات. إذا كنت تخطط لمشروع Blazor جديد أو تفكر في الترقية، فهذا هو الدليل الذي كنت أتمنى لو كان لدي عندما بدأت البحث في كل هذا.
نظرة سريعة إلى الوراء: كيف وصلنا إلى هنا
قبل .NET 8، كان عليك الالتزام بنموذج استضافة على مستوى المشروع. يعني Blazor Server أن كل شيء يعمل على الخادم عبر اتصال SignalR. يعني Blazor WebAssembly أن كل شيء يعمل في المتصفح. وكان لكل منهما مقايضات، وكان الاختلاط بينها مؤلما.
لقد غير .NET 8 اللعبة من خلال تقديم قالب مشروع واحد — تطبيق Blazor Web App — الذي يوحد كلا النموذجين. المفهوم الأساسي هو أوضاع العرض: عليك أن تقرر لكل مكون كيفية عرضه ومكان حدوث التفاعل. أصبح الإعداد الافتراضي هو SSR الثابت، مما يعني عرض المكونات على الخادم وإرسال HTML عادي إلى المتصفح - بدون SignalR، ولا WebAssembly، فقط HTML سريع.
قام .NET 9 بصقل هذه المفاهيم وتحسين تجربة المطورين وتحسين الأداء. يأخذ .NET 10 الأمر إلى أبعد من ذلك من خلال معالجة أفضل لإعادة الاتصال، وحالة المكون المستمرة عبر أوضاع العرض، وتحسينات على كيفية تسليم البرنامج النصي Blazor نفسه.
دعونا كسر كل شيء إلى أسفل.
أوضاع العرض في .NET 9
في قلب Blazor الحديث يوجد مفهوم أوضاع العرض. هناك أربعة أوضاع يجب أن تعرفها:
1. SSR الثابت (الافتراضي)
عند إنشاء تطبيق Blazor Web App جديد، يتم عرض المكونات بشكل ثابت على الخادم بشكل افتراضي. يقوم الخادم بمعالجة مكون Razor، وإنشاء HTML، وإرساله إلى المتصفح. لا يوجد اتصال مستمر، ولا وقت تشغيل WebAssembly — مجرد طلب/استجابة تقليدية.
يعد هذا مثاليًا للصفحات ذات المحتوى الثقيل، أو لوحات المعلومات التي تعرض البيانات في الغالب، أو أي صفحة لا تحتاج فيها إلى التفاعل في الوقت الفعلي.
@page "/products"
<h1>Our Products</h1>
@foreach (var product in products)
{
<div class="product-card">
<h3>@product.Name</h3>
<p>@product.Description</p>
<span class="price">@product.Price.ToString("C")</span>
</div>
}
@code {
private List<Product> products = new();
protected override async Task OnInitializedAsync()
{
products = await ProductService.GetAllAsync();
}
}
يتم عرض هذا المكون على الخادم، وينتج HTML، وهذا كل شيء. لا يوجد اتصال مستمر. تحميل أولي سريع، رائع لتحسين محركات البحث، الحد الأدنى من استخدام موارد الخادم.
2. الخادم التفاعليعندما تحتاج إلى التفاعل في الوقت الفعلي - التعامل مع نقرات الأزرار، ومعالجة إدخالات المستخدم، وتحديث واجهة المستخدم ديناميكيًا - يمكنك الاشتراك في وضع الخادم التفاعلي. يؤدي هذا إلى إنشاء اتصال SignalR بين المتصفح والخادم، وتحدث تحديثات واجهة المستخدم عبر هذا الاتصال.
@page "/counter"
@rendermode InteractiveServer
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
التوجيه @rendermode InteractiveServer هو كل ما يتطلبه الأمر. يتم عرض المكون في البداية على الخادم، ثم يتم إنشاء اتصال SignalR للتعامل مع التفاعلات اللاحقة. تعمل معالجات أحداث C# على الخادم، ويتم إرسال اختلافات واجهة المستخدم إلى المتصفح.
متى تستخدمه: عندما تحتاج إلى التفاعل، تحتاج مكوناتك إلى الوصول إلى الموارد من جانب الخادم (قواعد البيانات، وواجهات برمجة التطبيقات، وأنظمة الملفات)، وتريد تحميلًا أوليًا سريعًا دون انتظار تنزيل WebAssembly.
3. تجميع الويب التفاعلي
إذا كنت تريد التفاعل دون الحفاظ على اتصال الخادم، يقوم Interactive WebAssembly بتشغيل منطق المكون الخاص بك مباشرةً في المستعرض باستخدام وقت تشغيل .NET WebAssembly.
@page "/search"
@rendermode InteractiveWebAssembly
<h1>Product Search</h1>
<input @bind="searchTerm" @bind:event="oninput" placeholder="Search products..." />
@if (filteredProducts.Any())
{
<ul>
@foreach (var product in filteredProducts)
{
<li>@product.Name — @product.Price.ToString("C")</li>
}
</ul>
}
@code {
private string searchTerm = string.Empty;
private List<Product> allProducts = new();
private IEnumerable<Product> filteredProducts => allProducts
.Where(p => p.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase));
protected override async Task OnInitializedAsync()
{
allProducts = await Http.GetFromJsonAsync<List<Product>>("api/products") ?? new();
}
}
المقايضة: هناك تكلفة تنزيل أولية لوقت تشغيل .NET وتجميعاتك. ولكن بمجرد تحميله، يعمل المكون بالكامل في المتصفح دون الحاجة إلى رحلات ذهابًا وإيابًا للخادم لتفاعلات واجهة المستخدم.
متى يتم استخدامه: بالنسبة للمكونات التفاعلية للغاية حيث يكون زمن الاستجابة مهمًا (مثل: برامج تحرير النصوص الغنية، وأدوات الرسم، والتصفية في الوقت الفعلي)، أو عندما تريد تقليل تحميل الخادم، أو عندما تقوم بإنشاء تطبيق ويب تقدمي (PWA).
4. السيارات التفاعلية
هذه هي الأرضية الوسطى العملية وواحدة من ميزاتي المفضلة. يبدأ Interactive Auto بالعرض من جانب الخادم عبر SignalR للتحميل الأول، ثم يقوم بتنزيل وقت تشغيل WebAssembly في الخلفية بصمت. وفي الزيارات اللاحقة، يتم تشغيل المكون على WebAssembly.
@page "/dashboard"
@rendermode InteractiveAuto
<h1>Dashboard</h1>
<DashboardWidget Title="Sales" Value="@salesTotal" />
<DashboardWidget Title="Users" Value="@activeUsers" />
<button @onclick="RefreshData">Refresh</button>
@code {
private decimal salesTotal;
private int activeUsers;
protected override async Task OnInitializedAsync()
{
await RefreshData();
}
private async Task RefreshData()
{
var data = await DashboardService.GetSummaryAsync();
salesTotal = data.SalesTotal;
activeUsers = data.ActiveUsers;
}
}
يمنحك هذا أفضل ما في كلا العالمين: العرض الأول السريع (بدون انتظار تنزيل WASM)، وفي النهاية يتم تشغيل المكون من جانب العميل. لا يلاحظ المستخدم الانتقال.
متى تستخدمه: عندما تريد التحميل الأولي السريع والتنفيذ النهائي من جانب العميل. إنه خيار افتراضي رائع للعديد من المكونات التفاعلية.
بث SSR: أفضل ما في العالمين
يعد Streaming SSR إحدى تلك الميزات التي تبدو بسيطة ولكنها تحدث فرقًا كبيرًا في الأداء المتصور. إليك الفكرة: بدلاً من انتظار تحميل جميع بياناتك قبل إرسال أي HTML، يرسل الخادم غلاف الصفحة على الفور ثم يبث تحديثات المحتوى عندما تصبح البيانات متاحة.
@page "/reports"
@attribute [StreamRendering]
<h1>Monthly Reports</h1>
@if (reports is null)
{
<div class="loading-spinner">
<p>Loading reports...</p>
</div>
}
else
{
<table class="table">
<thead>
<tr>
<th>Month</th>
<th>Revenue</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
@foreach (var report in reports)
{
<tr>
<td>@report.Month</td>
<td>@report.Revenue.ToString("C")</td>
<td class="@(report.Growth >= 0 ? "text-success" : "text-danger")">
@report.Growth.ToString("P1")
</td>
</tr>
}
</tbody>
</table>
}
@code {
private List<MonthlyReport>? reports;
protected override async Task OnInitializedAsync()
{
// This might take a couple of seconds
reports = await ReportService.GetMonthlyReportsAsync();
}
}
مع السمة [StreamRendering]، إليك ما يحدث:
- يرسل الخادم على الفور HTML باستخدام أداة التحميل الدوارة.
OnInitializedAsyncيقوم بتشغيل وجلب البيانات.- عند وصول البيانات، يقوم الخادم بتدفق HTML المحدث (الجدول) إلى المتصفح.
- يقوم المتصفح بتصحيح DOM دون إعادة تحميل الصفحة بالكامل.
يرى المستخدم الصفحة على الفور مع مؤشر التحميل، ثم يملأ المحتوى. لا حاجة إلى إطار جافا سكريبت. لا يوجد اتصال WebSocket. مجرد استخدام ذكي لتدفق HTTP.متى يتم استخدامها: أي صفحة SSR ثابتة تقوم بجلب البيانات أثناء العرض. صفحات قائمة المنتجات ولوحات المعلومات والتقارير - في أي مكان قد يستغرق تحميل البيانات الأولية أكثر من بضع مئات من المللي ثانية.
متى لا تستخدمه: إذا تم تحميل البيانات بسرعة كبيرة (أقل من 100 مللي ثانية)، فإن الحمل الزائد للبث لا يستحق ذلك. كما أن دفق SSR لا يمنحك تفاعلًا مستمرًا - لذلك، لا تزال بحاجة إلى وضع عرض تفاعلي.
تحسين التنقل ومعالجة النماذج
أحد التحسينات الدقيقة ولكن القوية في Blazor الحديث هو التنقل المحسن. افتراضيًا، يعترض Blazor نقرات الروابط الداخلية وعمليات إرسال النماذج، ويجلب محتوى الصفحة الجديد عبر fetch ويصحح DOM بدلاً من القيام بالتنقل الكامل في المتصفح.
وهذا يعني أن التنقل بين صفحات SSR الثابتة يبدو وكأنه منتجع صحي - لا يوجد فلاش كامل للصفحة، ويمكن الحفاظ على موضع التمرير، وتكون التجربة سلسة للغاية.
كيف يعمل
عند تحميل البرنامج النصي Blazor (blazor.web.js)، فإنه يعترض تلقائيًا النقرات على الروابط الداخلية. بدلاً من التنقل التقليدي في المتصفح، فإنه:
- يقدم طلب
fetchإلى عنوان URL المستهدف. - يتلقى استجابة HTML.
- دمج المحتوى الجديد في DOM الحالي.
- يقوم بتحديث عنوان URL للمتصفح والتاريخ.
ليس عليك القيام بأي شيء لتمكين هذا - فهو قيد التشغيل افتراضيًا. ولكن يمكنك التحكم فيه:
<!-- Disable enhanced navigation for a specific link -->
<a href="/legacy-page" data-enhance-nav="false">Legacy Page</a>
<!-- Force a full page reload for external-like behavior -->
<a href="/downloads/report.pdf" data-enhance-nav="false">Download Report</a>
معالجة محسنة للنماذج
النماذج تحصل على نفس المعاملة. عند استخدام EditForm أو عنصر <form> القياسي مع معالجة نموذج Blazor، يتم اعتراض عمليات الإرسال والتعامل معها عبر fetch:
@page "/contact"
<EditForm Model="contactModel" OnValidSubmit="HandleSubmit" FormName="contact" Enhance>
<DataAnnotationsValidator />
<div class="mb-3">
<label for="name">Name</label>
<InputText id="name" @bind-Value="contactModel.Name" class="form-control" />
<ValidationMessage For="() => contactModel.Name" />
</div>
<div class="mb-3">
<label for="email">Email</label>
<InputText id="email" @bind-Value="contactModel.Email" class="form-control" />
<ValidationMessage For="() => contactModel.Email" />
</div>
<div class="mb-3">
<label for="message">Message</label>
<InputTextArea id="message" @bind-Value="contactModel.Message" class="form-control" />
<ValidationMessage For="() => contactModel.Message" />
</div>
<button type="submit" class="btn btn-primary">Send</button>
</EditForm>
@code {
[SupplyParameterFromForm]
private ContactModel contactModel { get; set; } = new();
private async Task HandleSubmit()
{
await ContactService.SubmitAsync(contactModel);
contactModel = new ContactModel();
}
}
السمة Enhance الموجودة على EditForm تطلب من Blazor اعتراض إرسال النموذج. يتم نشر النموذج على الخادم، ويقوم الخادم بمعالجته وإعادة عرض الصفحة، ويتم بث HTML المحدث مرة أخرى - كل ذلك بدون التنقل الكامل للصفحة. إنها تبدو تفاعلية، ولكنها مقدمة بالكامل من خلال الخادم.
لاحظ السمة [SupplyParameterFromForm] - هذه هي الطريقة التي يربط بها Blazor بيانات النموذج المنشورة بالنموذج الخاص بك في سيناريوهات SSR الثابتة. إنه الجسر بين منشورات النماذج التقليدية ونموذج مكونات Blazor.
التفاعل لكل صفحة ولكل مكون
أحد أقوى جوانب النموذج الجديد هو أنه يمكنك مزج أوضاع العرض داخل تطبيق واحد. يمكن أن تكون صفحة قائمة منتجاتك عبارة عن SSR ثابت، ويمكن أن تكون عربة التسوق الخاصة بك خادمًا تفاعليًا، ويمكن أن تكون أداة تكوين منتجك عبارة عن Interactive WebAssembly - كل ذلك في نفس التطبيق.
ضبط أوضاع العرض على مستوى المكون
يمكنك ضبط وضع التجسيد مباشرةً على أحد المكونات باستخدام التوجيه @rendermode:
@* This component is interactive via Server *@
@rendermode InteractiveServer
<h3>Live Chat</h3>
<!-- chat UI here -->
أو يمكنك ضبطه عند استخدام مكون من أحد الوالدين:
@page "/product/{Id:int}"
<h1>@product?.Name</h1>
<p>@product?.Description</p>
<!-- This child component gets its own interactive render mode -->
<ProductConfigurator Product="product" @rendermode="InteractiveWebAssembly" />
<!-- This stays static -->
<ProductReviews ProductId="Id" />
@code {
[Parameter] public int Id { get; set; }
private Product? product;
protected override async Task OnInitializedAsync()
{
product = await ProductService.GetByIdAsync(Id);
}
}
في هذا المثال، الصفحة نفسها عبارة عن SSR ثابت. يعمل المكون ProductConfigurator على WebAssembly من أجل تفاعل غني من جانب العميل. يظل المكون ProductReviews ثابتًا لأنه يعرض البيانات فقط.
ضبط أوضاع العرض على مستوى العالم
إذا كنت تريد أن تكون جميع الصفحات تفاعلية بشكل افتراضي، فيمكنك ضبط وضع العرض على مستوى الجذر في App.razor:
<Routes @rendermode="InteractiveServer" />
```وهذا يجعل كل صفحة تفاعلية عبر عرض الخادم. لا يزال بإمكان المكونات الفردية تجاوز هذا إذا لزم الأمر.
### قواعد مهمة يجب تذكرها
هناك بعض القيود التي يجب وضعها في الاعتبار عند مزج أوضاع العرض:
- **لا يمكن أن يحتوي المكون الفرعي على وضع عرض "أكثر تفاعلية" من المكون الأصلي. ** إذا كان الأصل ثابتًا، فيمكن أن يكون الأطفال ثابتين أو متفاعلين. ولكن إذا كان أحد الوالدين هو Interactive Server، فلا يمكن أن يكون الطفل Interactive WebAssembly (يجب أن يكون Server أو Auto).
- **لا يمكن للمكونات التفاعلية استخدام الخدمات المحددة مباشرة من الأصول الثابتة.** إذا تم تشغيل أحد المكونات على WebAssembly، فلن يتمكن من الوصول إلى مثيلات `DbContext` من جانب الخادم مباشرةً — ستحتاج إلى طبقة واجهة برمجة التطبيقات (API).
- **لا تنتقل الحالة تلقائيًا بين أوضاع التجسيد.** إذا تم عرض أحد المكونات مسبقًا على الخادم ثم قام بالتبديل إلى WebAssembly، فستحتاج إلى التعامل مع استمرار الحالة بشكل صريح - المزيد عن هذا في قسم .NET 10.
## ما الجديد في .NET 10
يواصل .NET 10 نهج التحسين التدريجي، مع التركيز على الموثوقية وتجربة المطور. فيما يلي أبرز مميزات تفاعل Blazor:
### تجربة إعادة الاتصال المحسنة
إذا كنت قد استخدمت وضع الخادم التفاعلي في الإنتاج، فمن المحتمل أنك واجهت تراكب إعادة الاتصال - تلك اللحظة التي ينقطع فيها اتصال SignalR ويرى المستخدم رسالة "جارٍ إعادة الاتصال...". في .NET 10، أصبحت هذه التجربة أفضل بشكل ملحوظ.
أصبح منطق إعادة الاتصال الآن أكثر ذكاءً فيما يتعلق بإعادة المحاولة. بدلاً من الفاصل الزمني الثابت لإعادة المحاولة، فإنه يستخدم إستراتيجية التراجع التي تتكيف مع الموقف. واجهة المستخدم أثناء إعادة الاتصال أصبحت أيضًا أكثر صقلًا، ولديك روابط أفضل لتخصيص التجربة:
```razor
<!-- In your App.razor or layout -->
<div id="components-reconnect-modal">
<div class="reconnect-visible">
<p>Connection lost. Attempting to reconnect...</p>
<div class="spinner"></div>
</div>
<div class="reconnect-failed">
<p>Could not reconnect to the server.</p>
<button onclick="location.reload()">Reload</button>
</div>
<div class="reconnect-rejected">
<p>Your session has expired.</p>
<a href="/">Return to Home</a>
</div>
</div>
يحاول إطار العمل الآن أيضًا إعادة الاتصال بقوة أكبر في حالات الفشل العابر، ويمكنه استعادة حالة الدائرة بشكل أكثر موثوقية. وهذا يعني عددًا أقل من لحظات “الرجاء إعادة تحميل الصفحة” للمستخدمين.
حالة المكون الثابتة عبر أوضاع العرض
هذه واحدة كبيرة. في .NET 9، عندما يتم عرض أحد المكونات مسبقًا على الخادم ثم ينتقل إلى WebAssembly (أو يقوم بالتبديل بين أوضاع العرض)، يتم فقدان حالة المكون. تتم إعادة تهيئة المكون بشكل فعال، مما قد يؤدي إلى عمليات جلب بيانات مكررة ووميض واجهة المستخدم.
يعمل .NET 10 على تحسين خدمة PersistentComponentState للعمل بسلاسة أكبر عبر انتقالات وضع العرض:
@page "/weather"
@rendermode InteractiveWebAssembly
@inject PersistentComponentState ApplicationState
<h1>Weather Forecast</h1>
@if (forecasts is null)
{
<p>Loading...</p>
}
else
{
@foreach (var forecast in forecasts)
{
<div class="forecast-card">
<h4>@forecast.Date.ToShortDateString()</h4>
<p>@forecast.Summary — @forecast.TemperatureC°C</p>
</div>
}
}
@code {
private List<WeatherForecast>? forecasts;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<List<WeatherForecast>>(
"weather-forecasts", out var restored))
{
// Data wasn't persisted from prerendering — fetch it
forecasts = await Http.GetFromJsonAsync<List<WeatherForecast>>("api/weather");
}
else
{
forecasts = restored;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("weather-forecasts", forecasts);
return Task.CompletedTask;
}
public void Dispose()
{
persistingSubscription.Dispose();
}
}
ومع التحسينات في .NET 10، يعمل هذا النمط بشكل أكثر موثوقية. تكون الحالة المتسلسلة أثناء العرض المسبق متاحة بشكل صحيح عند تهيئة المكون في وضعه التفاعلي، مما يؤدي إلى تجنب عمليات جلب البيانات المزدوجة والوميض القصير الذي قد يراه المستخدمون.
Blazor Script كأحد أصول الويب الثابتة
في الإصدارات السابقة، تم تقديم ملف Blazor JavaScript (blazor.web.js) من نقطة النهاية الداخلية لإطار العمل. في .NET 10، يتم تسليمه كأصل ويب ثابت. قد يبدو هذا تغييرًا بسيطًا، لكن له فوائد عملية:- تخزين مؤقت أفضل: تحصل أصول الويب الثابتة على رؤوس ذاكرة تخزين مؤقت مناسبة وعناوين URL ذات بصمات أصابع، بحيث تقوم المتصفحات بتخزينها بشكل أكثر فعالية.
- متوافق مع CDN: نظرًا لأنه ملف ثابت عادي، يمكن لشبكات CDN تخزينه مؤقتًا وتقديمه من مواقع التخزين المؤقت.
- الضغط: يتم تطبيق ضغط أصول الويب الثابت تلقائيًا، مما يؤدي إلى تقليل حجم البرنامج النصي على السلك.
لا تحتاج إلى تغيير كيفية الرجوع إليه — حيث يتعامل إطار العمل مع المسار المحدث تلقائيًا.
أفضل الممارسات: اختيار وضع العرض المناسب
بعد العمل مع كل هذه الأوضاع عبر العديد من المشاريع، إليك إطار القرار الخاص بي:
ابدأ بـ SSR الثابت
اجعل SSR الثابت هو الخيار الافتراضي. تتعلق معظم الصفحات في معظم التطبيقات بشكل أساسي بعرض البيانات. صفحات المنتج، ومنشورات المدونات، وملفات تعريف المستخدمين، وصفحات الإعدادات - لا تحتاج إلى تفاعل في الوقت الفعلي. يمنحك Static SSR أفضل أداء وأقل استخدام للموارد وأبسط نموذج عقلي.
أضف التفاعل عند الحاجة فقط
حدد المكونات المحددة التي تحتاج إلى الاستجابة لتفاعلات المستخدم في الوقت الفعلي. زر “أعجبني”، وأداة الدردشة، وواجهة السحب والإفلات - كلها تحتاج إلى التفاعل. لكن الصفحة المحيطة بهم ربما لا تفعل ذلك.
استخدم الوضع التلقائي التفاعلي باعتباره الوضع التفاعلي المفضل لديك
عندما تحتاج إلى التفاعل، غالبًا ما يكون Interactive Auto هو الخيار الافتراضي الأفضل. فهو يوفر لك تحميلات أولية سريعة (عرض الخادم) مع التنفيذ النهائي من جانب العميل (WebAssembly). يحصل المستخدم على أفضل ما في كلا العالمين، وتكتب الكود الخاص بك مرة واحدة.
حجز الخادم التفاعلي لحالات محددة
استخدم الخادم التفاعلي عندما:
- يحتاج المكون الخاص بك إلى الوصول المباشر إلى موارد الخادم (قواعد البيانات ونظام الملفات وواجهات برمجة التطبيقات الداخلية).
- يعد حجم تنزيل WebAssembly مصدر قلق ولا يمكنك استخدام Auto.
- أنت بحاجة إلى تشغيل المكون دائمًا على الخادم لأسباب أمنية (على سبيل المثال، معالجة البيانات الحساسة).
استخدم بث SSR بسخاء
إذا كانت صفحات SSR الثابتة تجلب أي بيانات، أضف [StreamRendering]. التكلفة ضئيلة والتحسن الملحوظ في الأداء كبير. يرى المستخدمون المحتوى يظهر بشكل تدريجي بدلاً من التحديق في صفحة فارغة.
تعامل مع انتقالات الحالة بعناية
إذا كنت تستخدم Interactive Auto أو تخلط العرض المسبق مع WebAssembly، فاستخدم دائمًا PersistentComponentState لتجنب عمليات جلب البيانات المكررة. سوف يشكرك المستخدمون على عدم وجود محتوى وامض.
ضع شجرة المكونات في الاعتبار
تذكر قواعد التسلسل الهرمي لوضع التجسيد. قم بتخطيط شجرة المكونات الخاصة بك بحيث تكون الحدود التفاعلية منطقية. النمط الشائع هو أن يكون لديك تخطيط ثابت مع “جزر” تفاعلية مضمنة عند الحاجة:
@* Layout: Static SSR *@
<header>
<NavMenu />
<UserMenu @rendermode="InteractiveServer" /> @* Needs real-time auth state *@
</header>
<main>
@Body
</main>
<footer>
<ChatWidget @rendermode="InteractiveAuto" /> @* Rich interactivity *@
</footer>
الخلاصة
يمثل نموذج التفاعل الخاص بـ Blazor في .NET 9 و.NET 10 أسلوبًا ناضجًا ومدروسًا جيدًا لبناء تطبيقات الويب. إن القدرة على اختيار أوضاع العرض لكل مكون، والتنقل المحسّن السلس، وتدفق SSR، والتحسينات المستمرة في إعادة الاتصال وإدارة الحالة تجعله خيارًا مقنعًا لمجموعة واسعة من التطبيقات.الفكرة الأساسية هي أن التفاعل عبارة عن نطاق، وليس خيارًا ثنائيًا. يمكن أن يكون معظم تطبيقك ثابتًا. تحتاج بعض الأجزاء إلى تفاعل يحركه الخادم. قد يستفيد البعض من التشغيل في المتصفح. يتيح لك Blazor الآن اتخاذ هذا الاختيار بأدق التفاصيل - المكون الفردي - دون محاربة إطار العمل.
إذا كنت تبدأ مشروعًا جديدًا، فإن نصيحتي بسيطة: أنشئ تطبيق Blazor Web App، وابدأ بـ SSR الثابت، وأضف [StreamRendering] إلى الصفحات المليئة بالبيانات، وقم بترقية المكونات الفردية إلى الأوضاع التفاعلية فقط عندما تحتاج إليها. سينتهي بك الأمر بالحصول على تطبيق سريع وفعال وقابل للتوسع بشكل جيد.
أتمنى لك حظًا سعيدًا في البرمجة، وكما هو الحال دائمًا، لا تتردد في التواصل معنا إذا كانت لديك أسئلة!