共用方式為


具有靜態伺服器端轉譯 (靜態 SSR) 的 ASP.NET Core Razor類別庫 (RCL)

注意

這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前的版本,請參閱 本文的 .NET 9 版本。

本文為考慮支援靜態伺服器端渲染 (static SSR) 的元件庫作者提供指引。

Blazor 鼓勵開發開放原始碼與商業元件庫的生態系統,正式稱為 Razor class libraries (RCLs)。 開發人員也可以建立可重複使用的元件,以便在自己公司內部的應用程式之間私下分享元件。 在理想情況下,元件是為了與盡可能多的裝載模型和轉譯模式相容而開發。 靜態 SSR 引進比互動式轉譯模式更具支援挑戰性的額外限制。

了解靜態 SSR 的功能和限制

靜態 SSR 是一種模式,元件會在伺服器處理傳入 HTTP 要求時執行。 Blazor 會將元件轉譯為 HTML,其包含在回應中。 傳送回應之後,伺服器端元件和轉譯器狀態會遭到捨棄,因此其餘的都會以 HTML 的形式留在瀏覽器中。

此模式的優點是更便宜、更可調整的裝載,因為不需要進行中的伺服器資源來保留元件狀態,瀏覽器與伺服器之間就不需要持續連線,而且瀏覽器中不需要 WebAssembly 承載。

所有現有的元件仍可與靜態 SSR 搭配使用。 不過,此模式的成本是無法執行事件處理程式,例如 @onclick†,原因如下:

  • 瀏覽器中沒有 .NET 程式碼可執行。
  • 伺服器已立即捨棄任何需要用來執行事件處理程式或轉譯相同的元件實例的元件和轉譯器狀態。

†無論轉譯模式為何,針對表單的 @onsubmit 事件處理常式有一特殊例外狀況,且一律執行。

這相當於元件在預先呈現期間的行為,在啟動線路或 .NET WebAssembly 運行時間之前BlazorSignalR。

對於唯一角色是產生唯讀 DOM 內容的元件,靜態 SSR 的這些表現方式已完全足夠。 不過,程式庫作者必須考慮在程式庫中包含互動式元件時應採取的方法。

元件作者的選項

有三個主要方法:

  • 請勿使用互動式表現方式 (基本)

    對於唯一角色是產生唯讀 DOM 內容的元件,開發人員不需要採取任何特殊動作。 這些元件自然會適用於任何轉譯模式。

    範例:

    • 「使用者卡片」元件會載入對應至人員的資料,並在具有相片、職稱和其他詳細資料的文體 UI 中轉譯。
    • 做為 HTML <video> 元素包裝函式的「視訊」元件,可讓您更方便在 Razor 元件中使用。
  • 需要互動式轉譯 (基本)

    您可以選擇要求您的元件只搭配互動式轉譯使用。 這會限制元件的適用性,但這表示您可以自由依賴任意事件處理程式。 即便如此,您仍應該避免宣告特定 @rendermode ,並允許取用程式庫的應用程式作者選取一個。

    範例:

    • 視訊編輯元件,使用者可以將視訊的片段拼接和重新排序。 即使有辦法以純 HTML 按鈕和表單貼文來代表這些編輯作業,但如果沒有真正的互動性,使用者體驗是無法接受的。
    • 共同作業文件編輯器,必須實時顯示其他使用者的活動。
  • 使用互動式表現方式,但設計靜態 SSR 和漸進式增強功能 (進階)

    許多互動式表現方式只能使用 HTML 功能來實作。 對於 HTML 和 CSS 有很好的理解,您通常會產生適用於靜態 SSR 的實用功能基準。 您仍然可以宣告實作更進階的選擇性表現方式的事件處理程式,這些處理程式只能在互動式轉譯模式中運作。

    範例:

    • 格線元件。 在靜態 SSR 下,元件可能只支援顯示資料,並在頁面之間巡覽(使用 <a> 連結實作)。 搭配互動式轉譯使用時,元件可能會新增即時排序和篩選。
    • 索引標籤元件。 只要使用 <a> 連結達成索引標籤之間的瀏覽,且狀態只保留在 URL 查詢參數中,元件就可以在沒有 @onclick的情況下運作。
    • 進階檔案上傳元件。 在靜態 SSR 下,元件可能像原生 <input type=file>一樣運作。 搭配互動式轉譯使用時,元件也可以顯示上傳進度。
    • 股票行情指示器。 在靜態 SSR 下,元件可能會在轉譯 HTML 時顯示股票報價。 搭配互動式轉譯使用時,元件可以即時更新股價。

針對上述任何策略,您也可以選擇使用 JavaScript 實作互動式功能。

若要在這些方法中選擇,可重複使用的 Razor 元件的作者必須進行成本/權益取捨。 如果您的元件支援所有轉譯模式,包括靜態 SSR,您的元件會更實用,而且具有更廣泛的潛在使用者基底。 不過,設計及實作支援並充分利用每個轉譯模式的元件需要更多工作。

使用 @rendermode 指示詞的時機

在大部分情況下,可重複使用元件的作者 應該指定轉譯模式,即使需要互動。 這是因為元件作者不知道應用程式是否支援 InteractiveServerInteractiveWebAssembly或兩者搭配 InteractiveAuto。 如果未指定 @rendermode,元件作者會將選擇留給應用程式開發人員。

即使元件作者認為需要互動功能,應用程式作者仍可能認為它足以單獨使用靜態 SSR。 例如,具有拖曳和縮放互動功能的地圖元件似乎需要互動功能。 不過,某些案例可能只會呼叫轉譯靜態地圖影像,並避免拖曳/縮放功能。

可重複使用元件的作者應該在其元件上使用 @rendermode 指示詞的唯一原因是,如果實作基本上結合至一個特定的轉譯模式,而且在不同的模式中使用,肯定會造成錯誤。 請考慮具有使用 Windows 或 Linux 特定 API 直接與主機 OS 互動之核心用途的元件。 在 WebAssembly 上可能無法使用這類元件。 如果是,則為元件宣告 @rendermode InteractiveServer 是合理的。

串流轉譯

可重複使用的 Razor 元件可以為 串流轉譯 自由宣告 @attribute [StreamRendering][StreamRendering] 屬性 API)。 這會導致靜態 SSR 期間的累加 UI 更新。 由於相同的數據載入模式會在互動式轉譯期間產生累加 UI 更新,不論是否存在 [StreamRendering] 屬性,元件在所有情況下都能正確運作。 即使在伺服器上隱藏串流靜態 SSR 的情況下,元件仍會轉譯其正確的最終狀態。

可重複使用的 Razor 元件可使用連結和加強巡覽功能。 HTML <a> 標籤應該產生具有或沒有互動式 Router 元件的對等行為,以及 DOM 中上階層級是否啟用/停用增強式瀏覽。

跨轉譯模式使用表單

可重複使用的 Razor 元件可能包含表單( <form><EditForm>),因為這些元件可以實作,以在靜態和互動式轉譯模式中同等地運作。

請考慮下列範例:

<EditForm Enhance FormName="NewProduct" Model="Model" OnValidSubmit="SaveProduct">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <p><label>Name: <InputText @bind-Value="Item.Name" /></label></p>

    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Product? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private async Task Save()
    {
        ...
    }
}

EnhanceFormNameSupplyParameterFromFormAttribute API 只會在靜態 SSR 期間使用,並在互動式轉譯期間忽略。 表單在互動式和靜態 SSR 期間都能正常運作。

避免靜態 SSR 特有的 API

HttpContext 只能在靜態 SSR 期間使用,因此在建立跨轉譯模式運作的元件時,請勿依賴 HttpContextHttpContext API 在互動式轉譯期間沒有意義,因為當時在發行小眾測試版中沒有使用中的 HTTP 要求。 考慮設定 HTTP 狀態程式碼或寫入 HTTP 回應是毫無意義的。

可重複使用的元件可在可用時免費接收 HttpContext ,如下所示:

[CascadingParameter]
public HttpContext? Context { get; set; }

此值在互動式轉譯期間為 null ,而且只會在靜態 SSR 期間設定。

在許多情況下,有比使用 HttpContext更好的替代方法。 如果您需要知道目前的 URL 或執行重新導向, NavigationManager 的 API 可適用於所有轉譯模式。 如果您需要知道使用者的驗證狀態,請使用 Blazor的 AuthenticationStateProvider 服務 (AuthenticationStateProvider 文件),而不是使用 HttpContext.User