1. 程式人生 > 其它 >Blazor Server 和 WebAssembly 應用程式入門指南

Blazor Server 和 WebAssembly 應用程式入門指南

翻譯自 Waqas Anwar 2021年3月12日的文章 《A Beginner’s Guide To Blazor Server and WebAssembly Applications》 [1]

如果您一直緊跟 .NET 世界的最新發展趨勢,那麼現在您一定聽說過 Blazor。目前在 .NET 社群中有很多關於 Blazor 的宣傳,這種宣傳最常見的原因是它引入了一些大多數 .NET 開發人員十幾年來一直夢寐以求的東西,即:既可以在服務端又可以在瀏覽器中執行 C# 的能力。Blazor 允許我們使用 HTML、CSS 和 C#(而不是 JavaScript)來構建互動式 Web 應用程式。在本教程中,我將介紹 Blazor 的基本概念,並概述可用於 Blazor 的不同的託管模型。我還將介紹每種託管模型的優缺點,以便您可以為下一個 Blazor 專案託管模型做出最佳的決定。

Blazor 是什麼?

Blazor 是一個免費、開源的單頁應用程式(SPA)開發框架,使開發人員能夠在服務端和客戶端上使用 C# 構建互動式 Web 應用程式。Blazor 不需要在客戶端上安裝任何外掛來在瀏覽器中執行 C#/.NET 程式碼。它使用 WebAssembly 執行 .NET 程式碼,WebAssembly 是所有主流瀏覽器都支援的 Web 標準。Blazor 還可以在服務端執行 .NET 程式碼並構建 UI,然後通過 SignalR 連線僅將更新的 DOM 傳輸到客戶端。

WebAssembly 是什麼?

WebAssembly(有時簡寫為 Wasm)是一種可移植的二進位制格式(低階指令集),被設計用於在任何能夠解釋這些指令的主機上執行。WebAssembly 的主要目標是允許開發人員構建高效能的 Web 應用程式,但其格式也被設計為可執行於和整合到其他環境中。WebAssembly 目前受到了所有主流瀏覽器的支援,比如 Chrome、Android 版 Chrome、Edge、Firefox、Safari、Opera 等。

Blazor 託管模型

Blazor 元件模型是 Blazor 的核心,它的設計方式使計算 UI 更改和呈現 UI 彼此分離。 這就是為什麼無論您使用何種方式渲染您的應用程式,基本的元件模型都保持不變的原因。 在撰寫本文時,有四種渲染/託管模型可用,它們都處於不同的開發階段。

  1. Blazor Server
  2. Blazor WebAssembly
  3. Blazor Electron
  4. Mobile Blazor Bindings

Blazor Electron 和 Mobile Blazor Bindings 目前處於實驗階段,Microsoft 尚未承諾釋出這些託管模型,因此我不會在本文中討論它們。

Blazor Server App 是什麼?

Blazor Server 應用程式在伺服器上執行,可享受完整的 .NET Core 執行時支援。所有處理都在伺服器上完成,UI/DOM 更改通過 SignalR 連接回傳給客戶端。這種雙向 SignalR 連線是在使用者第一次從瀏覽器中載入應用程式時建立的。 由於 .NET 程式碼已經在伺服器上執行,因此您無需為前端建立 API。您可以直接訪問服務、資料庫等,並在傳統的服務端技術上做任何您想做的事情。

何時使用 Blazor Server

  1. 當您想在完整的 .NET Core 執行時上執行應用程式時
  2. 當您想要保持應用程式的初始下載大小非常小時
  3. 當您想保持應用啟動時間非常快時
  4. 當您想把應用程式的程式碼保留在伺服器上,而不希望它被下載到客戶端時
  5. 當您想要一個快速的應用開發週期,而現有的 .NET 開發人員幾乎不需要學習曲線時
  6. 當您想讓您的應用對搜尋引擎友好時
  7. 當您希望應用程式在舊的瀏覽器上執行,而不依賴於 WebAssembly 時
  8. 當您想在 Visual Studio 中像除錯普通 .NET 應用程式一樣除錯 .NET 程式碼時
  9. 當您想要構建內部網或低需求的面向公眾的應用程式時

何時不要使用 Blazor Server

  1. 當您的應用程式在高延遲環境中執行時
  2. 當您希望您的應用程式離線工作,而不需要一個與伺服器的固定 SignalR 連線時
  3. 當您不想增加伺服器資源以響應大量連線的 SignalR 客戶端時

Blazor WebAssembly App 是什麼?

這種託管模型是現代流行的 SPA 框架(比如 Angular、Vue 和 React)的直接競爭對手,也是大多數開發人員有興趣學習 Blazor 的主要原因。它允許開發人員使用 C# 取代 JavaScript 編寫所有前端 UI 邏輯。在這種託管模型中,第一次請求時,會將應用程式的 DLL 及其所有依賴項和小尺寸的 Mono .NET 執行時下載到客戶端。然後,客戶端中的 Mono 執行時就會載入並執行應用程式程式碼。Blazor WebAssembly 程式可以用 C、C# 等其他語言編寫,然後編譯成 WebAssembly 位元組碼。

何時使用 Blazor WebAssembly

  1. 當您想要將整個應用程式編譯為靜態檔案,並將它們提供給客戶端,而不需要伺服器上的 .NET 執行時時。這意味著您的後端可以用 PHP、Node 或 Rails 編寫,並服務於用 Blazor 編寫的前端應用程式。
  2. 當您想要構建可以在客戶端離線執行而無需持續連線到服務端的應用程式時。
  3. 當您想要將處理轉移到客戶端並減少服務端的負載時。
  4. 當您想在客戶端和服務端之間共享程式碼和庫時。

何時不要使用 Blazor WebAssembly

  1. 當由於下載到客戶端的檔案/DLL 太多,而您無法在有效負載上妥協時。
  2. 當您無法在緩慢的啟動時間上(特別是在網路連線不佳的情況下)妥協時。
  3. 當您無法妥協於應用程式必須執行在具有完整的安全限制的瀏覽器沙箱環境中時。

為了更好地理解 Blazor 託管模型,讓我們在 Visual Studio 2019 中分別建立一個 Blazor Server 和 Blazor WebAssembly 應用程式。

在 Visual Studio 2019 中建立 Blazor Server 應用

開啟 Visual Studio 2019 並點選建立新專案。從可用的模板列表中選擇 Blazor App 模板並點選下一步

指定專案名稱(比如 BlazorServerApp)並點選下一步。您將看到下面的對話方塊,詢問您選擇要建立的 Blazor 應用程式的型別。我們要建立 Blazor Server 應用,所以請選擇 Blazor Server App 並點選 建立 按鈕。

Visual Studio 將為我們建立一個 Blazor Server 應用程式,其中在解決方案資源管理器中包含以下資料夾和檔案。

讓我們來討論一下 Blazor Server App 中可用的一些重要檔案和資料夾。

Program.cs

這個檔案包含 Main 方法,它是專案的入口點。Main 方法中呼叫 CreateHostBuilder 方法,為我們配置預設的 ASP.NET Core 宿主。

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }
 
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<startup>();
            });
}

Startup.cs

它與我們在標準 ASP.NET Core 專案中使用的檔案相同。需要重點注意的一點是 ConfigureServices 方法中呼叫了 AddServerSideBlazor,該方法新增與 Blazor Server App 相關的服務。

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddSingleton<weatherforecastservice>();
}

在此檔案的 Configure 方法中我們還有以下兩行重要的程式碼。MapBlazorHub 方法配置 Blazor Server App 所需的 SignalR Hub Endpoints。MapFallbackToPage 方法會將所有未與任何控制器、razor 頁面等匹配的請求對映到 _Host 頁面,這將允許所有動態內容請求路由到 SPA 框架,而不是丟擲 404 Not Found

app.UseEndpoints(endpoints =>
{
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

_Host.cshtml

這是應用程式的根頁面,每個 Razor 元件/頁面都將在此 host 頁面中呈現。它具有基本的 HTML 元素,例如 html、head 和 body,以及一些特殊元素。請注意,Blazor 是一個基於元件的框架,Blazor 中的每一內容都是一個元件。<component> 指定了我們想讓應用程式根元件呈現的位置。

<component type="typeof(App)" render-mode="ServerPrerendered">

該檔案還在末尾註入了 blazor.server.js 檔案,此 JavaScript 檔案包含設定 SignalR 連線到服務端的程式碼。此連線在瀏覽器載入應用程式後立即建立,然後被用於服務端和客戶端瀏覽器之間的實時通訊。如果您想了解有關 SignalR 的更多知識,請閱讀我的文章 Display Live Sports Updates using ASP.NET Core SignalR[2]

<script src="_framework/blazor.server.js"></script>

App.razor

這是 Blazor App 的主要元件,其主要工作是攔截路由並呈現 FoundNotFound 元件。 如果找到與路由匹配的元件,則呈現 Found 元件,如果未找到匹配的元件,則呈現 NotFound 元件。

<router appassembly="@typeof(Program).Assembly" preferexactmatches="@true">
    <found context="routeData">
        <routeview routedata="@routeData" defaultlayout="@typeof(MainLayout)">
    </routeview></found>
    <notfound>
        <layoutview layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </layoutview>
    </notfound>
</router>

MainLayout.cshtml

MainLayout 檔案包含應用程式的主佈局,其標記可以被多個 Razor 元件共享。這個佈局元件通常包含應用程式的常見 UI 元素,例如頁首、選單、頁尾、側邊欄等。為我們生成的預設 MainLayout 有一個側邊欄,用來渲染 NavMenu 元件,它還使用 Razor 語法 @Body 來指定其他元件的內容將在佈局標記中呈現的位置。

@inherits LayoutComponentBase
 
<div class="page">
    <div class="sidebar">
        <navmenu>
    </navmenu></div>
 
    <div class="main">
        <div class="top-row px-4">
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>
 
        <div class="content px-4">
            @Body
        </div>
    </div>
</div>

wwwroot 資料夾

該資料夾包含靜態檔案,例如圖片、字型、圖示、CSS 和 JavaScript 檔案等。

Pages 和 Shared 資料夾

該資料夾包含我們之前討論過的 _Host.cshtml 檔案以及一些 Razor 元件。Blazor 應用程式是具有 .razor 副檔名的 Razor 元件的集合。其中一些元件稱為可路由元件,因為可以使用其路由訪問它們。例如,當我們導航到應用程式根 URL 時,將呈現下面的 Index.razor 元件。該 URL 是使用 Index.razor 元件頂部的 @page 指令指定的。

Index.razor

@page "/"
 
<h1>Hello, world!</h1>
 
Welcome to your new app.
 
<surveyprompt title="How is Blazor working for you?">

請注意,上面的頁面還使用了一個子元件 SurveyPrompt,之所以稱它為子元件,是因為它沒有 @page 指令,它可以被嵌入到其他元件中。

Pages 資料夾中還有一些其他的 razor 元件,這些元件都可以使用檔案頂部指定的路徑進行訪問。例如,當我們導航到 /counter 路徑時,Counter 元件將呈現。類似地,FetchData 元件將使用 /fetchdata 路徑呈現。

Razor Server 應用程式還有一個包含共享元件的 Shared 資料夾。這些元件可以被整個應用程式中的任何元件使用,就像我們上面看到的 SurveyPrompt 元件一樣。Shared 資料夾中另一個有趣的共享元件是 NavMenu 元件,它呈現 Blazor Server 應用程式的頂部導航欄。

_Imports.razor

該檔案類似於我們在 ASP.NET MVC Web 應用程式中的 _ViewImports.cshtml 檔案,它包含我們可以在不同 razor 元件中使用的名稱空間列表。在 _Imports.razor 檔案中宣告所有這些名稱空間的好處是我們不需要在每個 razor 元件中重複引入它們。

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop 

現在是時候執行我們的 Blazor Server 應用程式並在瀏覽器中檢視它的執行情況了。在 Visual Studio 中按 F5,您將看到一個漂亮的預設 Blazor Server 應用程式。試試從側邊欄導航到不同的頁面,並嘗試在 Counter 頁面上使用計數器,您會注意到沒有頁面重新整理或回傳到伺服器。一切都像經典的 SPA 那樣流暢和快速,瀏覽器和服務端的所有通訊都是使用 SignalR 連線進行的。

您也可以開啟瀏覽器開發者工具,您會注意到所有標準的 CSS 和 JavaScript 檔案(包括 blazor.server.js 檔案)都下載到了客戶端,並通過 Web Sockets 建立了一個 SignalR 連線。

在 Visual Studio 2019 中 建立 Blazor WebAssembly 應用

我們已經瞭解了 Blazor Server App 的基礎知識,並在瀏覽器中看到了它的執行情況。現在讓我們建立一個 Blazor WebAssembly App,以便我們可以理解它們的不同之處。按照我們上面提到的相同步驟,並使用 Blazor App 模板在 Visual Studio 中建立一個新的 Blazor 應用程式。當您被詢問選擇 Blazor App 的型別時,這次需要選擇 Blazor WebAssembly App

Visual Studio 將為我們建立一個 Blazor WebAssembly 應用程式,其中在解決方案資源管理器中包含以下資料夾和檔案。

您可以輕鬆發現這兩種型別的應用程式之間的一些差異。例如,在 Blazor WebAssembly 應用程式中沒有以下檔案:

  1. _Host.cshtml
  2. Error.cshtml
  3. Startup.cs
  4. appsettings.json

index.html

在 Blazor WebAssembly 應用程式中,我們會在 wwwroot 資料夾中有一個 index.html 檔案,作為主頁面, 該檔案在末尾註入了 blazor.webassembly.js 檔案,此檔案由框架提供以處理下載 .NET 執行時、Blazor 應用程式及其所有依賴項。它還包含為了執行應用而初始化執行時的程式碼。

Program.cs

在 Blazor WebAssembly 應用程式中,應用程式的根元件在 Program.cs 檔案中的 Main 方法中指定。應用程式的根元件是 App.razor,你可以看到它是如何被新增到 RootComponents 集合中的。

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<app>("#app");
 
        builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
 
        await builder.Build().RunAsync();
    }
}

在 Visual Studio 中按 F5,您將看到一個相似的 Blazor WebAssembly 應用程式。嘗試從側邊欄導航到不同的頁面,並嘗試像之前在 Blazor Server App 中所做的那樣在 Counter 頁面上使用計數器。 一切看起來感覺一模一樣,也沒有伺服器端回傳。

正如我們已經知道的那樣,Blazor WebAssembly 應用程式會在客戶端下載應用程式及其所有依賴項,因此如果您開啟瀏覽器開發者工具,會看到客戶端下載了大量 DLL(只會在第一次瀏覽時下載)。

以上所有檔案只會在第一次請求時下載,然後它們被快取在瀏覽器中。如果您再次重新整理頁面,將會看到這一次下載的檔案很少。

總結

在本文中,我試圖為您介紹 Blazor SPA 框架的基本概念,我們看到了兩個 Blazor 應用程式使用兩種不同的託管模型進行託管。因為 Blazor 框架嚴重依賴於 razor 元件,所以兩個專案中的大部分程式碼和檔案都是相同的。這些元件是 Blazor 應用程式的構建塊,無論使用哪種託管模型,我們都可以以相似的方式構建這些元件。如果您喜歡本文,請分享它並傳播知識。


作者 : Waqas Anwar
翻譯 : 技術譯站
連結 : 英文原文


  1. https://www.ezzylearning.net/tutorial/a-beginners-guide-to-blazor-server-and-webassembly-applications A Beginner’s Guide To Blazor Server and WebAssembly Applications ↩︎

  2. https://www.ezzylearning.net/tutorial/display-live-sports-updates-using-asp-net-core-signalr Display Live Sports Updates using ASP.NET Core SignalR ↩︎