在上一篇 .NET 8 Blazor 002 - 了解 互動式伺服器端轉譯 Interactive server-side rendering (interactive SSR) 運作模式 介紹了 .NET 8 Blazor 支援的轉譯模式,這裡將介紹了互動式伺服器端轉譯 Interactive server-side rendering (interactive SSR) 運作模式,這是一種採用讓 Blazor 應用程式在伺服器端進行渲染,然後再將渲染結果傳送給客戶端。這樣的機制會有一個先天潛在的缺陷,那就是這樣的應用需要在網路持續有效的情況下,才能夠正常運作。
在這篇文章中,將會要來介紹 .NET 8 Blazor 支援的另一種轉譯模式,這種模式是互動式 WebAssembly 用戶端端轉譯 Client-side rendering (CSR) 運作模式,這是一種採用讓 Blazor 應用程式在客戶端進行渲染,也就是說,這個網頁的相關執行邏輯與互動操作事件,都會在客戶端上來執行,然後再將渲染結果傳送給伺服器端。
總結來說,這個模式是一種介於 SSR 與 CSR 之間的模式。用戶端與伺服器端之間的溝通,是透過 SignalR 這個技術來進行。伺服器端僅會將要渲染內容的差異部分傳送給客戶端,這樣可以讓 Blazor 應用程式在客戶端的效能得到提升。缺點就是,這個系統必須要在網路持續有效的情況下,才能夠正常運作。
但是,這個機制也存在著一個缺點,那就是在第一次開啟網頁來使用的時候,會需要載入一些必要的資源,這樣會造成一些等待時間,這個等待時間會讓使用者感到不便,所以在這個模式下,需要透過一些技術手段來進行優化,以提升使用者的體驗。
所謂的 WebAssembly 是一種可以讓網頁應用程式在瀏覽器中執行的一種技術,透過 WebAssembly 技術,可以讓我們在瀏覽器中執行一些較為複雜的應用程式,這樣可以讓我們的網頁應用程式更加的強大。現今的瀏覽器都已經支援了 WebAssembly 技術,所以可以放心的使用這個技術。透過 Wasm 技術的加持,可以讓 .NET & C# 開發出來的程式碼,可以在瀏覽器中執行,這樣可以讓我們的程式碼更加的強大,而不再需要限縮只能夠使用 JavaScript 程式語言了。
請依照底下的操作,建立起這篇文章需要用到的練習專案
- 打開 Visual Studio 2022 IDE 應用程式
- 從 [Visual Studio 2022] 對話窗中,點選右下方的 [建立新的專案] 按鈕
- 在 [建立新專案] 對話窗右半部
- 切換 [所有語言 (L)] 下拉選單控制項為 [C#]
- 切換 [所有專案類型 (T)] 下拉選單控制項為 [Web]
- 在中間的專案範本清單中,找到並且點選 [Blazor Web App] 專案範本選項
A project template for creating a Blazor Web app that support both server-side rending and client interactivity. This template can be used for web apps with rich dynamic user interfaces (UIs)
- 點選右下角的 [下一步] 按鈕
- 在 [設定新的專案] 對話窗
- 找到 [專案名稱] 欄位,輸入
csBlazorCSR
作為專案名稱 - 在剛剛輸入的 [專案名稱] 欄位下方,確認沒有勾選 [將解決方案與專案至於相同目錄中] 這個檢查盒控制項
- 點選右下角的 [下一步] 按鈕
- 現在將會看到 [其他資訊] 對話窗
- 在 [架構] 欄位中,請選擇最新的開發框架,這裡選擇的 [架構] 是 :
.NET 8.0 (長期支援)
- 在 [驗證類型] 欄位中,請選擇 [無]
- 勾選 [針對 HTTPS 進行設定] 檢查盒欄位
- 在 [Interactive render mode] 欄位中,請選擇 [WebAssembly]
- 在 [Interactivity location] 欄位中,請選擇 [Per pages/component]
- 勾選 [Include sample pages] 檢查盒欄位
- 勾選 [Do not use top-level statements] 檢查盒欄位
這裡的這個操作,可以由讀者自行決定是否要勾選這個檢查盒控制項
- 不要勾選 [在 .NET Aspire 協調流程中登入] 檢查盒欄位
- 請點選右下角的 [建立] 按鈕
稍微等候一下,這個 Blazor Web App 專案將會建立完成
在上述的操作過程中,建立了一個 [csBlazorCSR] 方案,在這個方案內建立了兩個專案,分別是 [csBlazorCSR] / [csBlazorCSR.Client];在這個 [csBlazorCSR] 專案內,將會參考到 [csBlazorCSR.Client] 專案。
在這兩專案內,都會有 Program.cs 檔案
在 [csBlazorCSR] 專案的根目錄下,找到 Program.cs
檔案,並且打開這個檔案,這個檔案的內容如下
第一篇文章所建立的專案,僅僅使用了 builder.Services.AddRazorComponents();
,為了要在這個專案內可以使用互動式 WebAssembly 用戶端端轉譯 Client-side rendering (CSR) 運作模式,需要在 Program.cs
檔案中加入 AddInteractiveWebAssemblyComponents()
這個服務,這樣就可以在這個專案內使用互動式 WebAssembly 用戶端端轉譯 Client-side rendering (CSR) 運作模式。
另外,在 app.MapRazorComponents<App>()
這個方法中,加入 ..AddInteractiveWebAssemblyRenderMode()
與 .AddAdditionalAssemblies(typeof(Client._Imports).Assembly)
方法,這樣就可以在這個專案內使用互動式 WebAssembly 用戶端端轉譯 Client-side rendering (CSR) 運作模式。而對於這個方法 .AddAdditionalAssemblies(typeof(Client._Imports).Assembly)
的呼叫,是為了讓這個專案可以使用到 [csBlazorCSR.Client] 專案內的組件。
在 [Program.cs] 檔案中的其他內容就沒有太大的差異了。
using csBlazorCSR.Client.Pages;
using csBlazorCSR.Components;
namespace csBlazorCSR
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Client._Imports).Assembly);
app.Run();
}
}
}
在 [csBlazorCSR] 專案的根目錄下,找到 Program.cs
檔案,並且打開這個檔案,這個檔案的內容如下
這個 [Program.cs] 檔案為 Wasm 服務的程式碼進入點,任何需要透過 WebAssembly 來執行的程式碼,若需要用到的相依性注入服務,則需要在這裡進行宣告與註冊這些服務到 IoC DI 容器內。
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
namespace csBlazorCSR.Client
{
internal class Program
{
static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
await builder.Build().RunAsync();
}
}
}
從 [Components] 資料夾內找到並且打開 [App.razor] 這個檔案,就會看到底下內容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="csBlazorCSR.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
這裡使用的 [App.razor] 檔案內容,與第一篇文章所建立的專案內容是一樣的,這裡的內容是用來設定 Blazor 應用程式的根元件,這個根元件將會用來載入其他的 Razor 元件。
在 [Components] 資料夾內找到並且打開 [Routes.razor] 這個檔案,就會看到底下內容
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Client._Imports).Assembly }">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
這裡使用的 [Routes.razor] 檔案內容,與前一篇文章所建立的專案內容大致相同,這裡的內容是用來設定 Blazor 應用程式的路由元件,這個路由元件將會用來顯示路由的內容。
不過,在這裡用到的 [Router] 元件內,有用到 AdditionalAssemblies
這個屬性,這個屬性是用來設定這個 Blazor 應用程式所需要用到的組件,這樣就可以讓這個 Blazor 應用程式可以使用到這些組件(存在於 [csBlazorCSR.Client] WebAssembly 專案內)。
也就是說,在這種開發模式下,Blazor 應用程式的組件可以分散在不同的專案內,透過這個 AdditionalAssemblies
這個屬性,可以讓 Blazor 應用程式可以使用到這些組件。
現在再次執行這個專案,接著,開啟無痕視窗
按下 F12 按鍵,進入到開發人員模式,切換到 [Network] 標籤頁次,接著在網址列輸入 https://localhost:7228/
,就會看到底下的畫面
因為這個專案的首頁元件,採用的是 靜態 SSR 方式來渲染,所以在這個畫面中,可以看到有一個 index
的請求,這個請求是用來取得首頁的內容,這個內容是在伺服器端進行渲染,然後再將渲染結果傳送給客戶端。
在 [csBlazorCSR] 專案的 [Components] > [Pages] 資料夾內,找到並且打開 [Home.razor] Razor 元件,這個元件就是用來顯示首頁的內容,這個元件的內容如下
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
從該元件所在的專案位置與該元件的內容來看,這個元件是用來顯示首頁的內容,這個元件的內容是在伺服器端進行渲染,然後再將渲染結果傳送給客戶端。
這個計數器元件位於 [csBlazorCSR.Client] 專案內,請在此專案內 [Pages] 資料夾內找到,並且找到並且打開 [Counter.razor] 這個檔案,就會看到底下內容
@page "/counter"
@rendermode InteractiveWebAssembly
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
在這個 [Counter.razor] 計數器之 Razor 元件中,可以看到,這裡使用了 @rendermode InteractiveWebAssembly
這個語法,宣告這個頁面需要採用 [互動式 WebAssembly 用戶端端轉譯 Interactive WebAssembly Client-side rendering (Interactive CSR)] 模式。
從開發人員模式視窗的 [Network] 頁籤內的訊息內容,可以看到底下的畫面
這裡可以看到,當 [Counter] 頁面被載入後,因為這是一個要採用 CSR 渲染模式,而此時這個瀏覽器環境中,尚未存在 .NET Runtime 的 WebAssembly 程式碼,因此,將會需要檔案,如 .NET CLR / 各種 .NET 組件檔案,這些檔案將會被載入到瀏覽器中,這樣才能夠讓這個 Blazor 應用程式可以在瀏覽器中執行。
現在,請重新整理這個網頁,就會看到底下的畫面
從這裡可以看到,因為 .NET 需要用到的 WebAssembly 程式碼已經被載入到瀏覽器中,所以,這裡就直接顯示了計數器的內容,這個內容是在客戶端進行渲染。
所以,對於想要執行 CSR 的元件,瀏覽器中必須要有 .NET Runtime 與相關的組件 WebAssembly 程式碼,這樣才能夠正常的執行。
沒有留言:
張貼留言