ASP.NET 核心 Razor 類別庫 (RCL) 與靜態伺服器端轉譯 (靜態 SSR)

本文針對考慮支持靜態伺服器端轉譯 (static SSR) 的元件庫作者提供指引。

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

了解靜態 SSR 的功能和限制

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

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

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

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

†無論轉譯模式為何,表單事件處理程式 @onsubmit 的特殊例外狀況一律正常運作。

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

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

元件作者的選項

有三個主要方法:

  • 請勿使用互動式行為 (基本)

    對於唯一角色是產生唯一 這些元件自然會使用任何轉譯模式。

    範例:

    • 「使用者卡片」元件,會載入對應至人員的數據,並在具有相片、職稱和其他詳細數據的文體 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>Name: <InputText @bind-Value="Item.Name" /></p>

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

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

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

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

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

避免靜態 SSR 特有的 API

若要讓可重複使用的元件在所有轉譯模式中運作,請勿依賴 HttpContext ,因為它只能在靜態 SSR 期間使用。 HttpContext API 在互動式轉譯期間沒有意義,因為當時在正式發行前小眾測試版中沒有作用中的 HTTP 要求。 考慮設定狀態代碼或寫入回應是毫無意義的。

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

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

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

在許多情況下,替代方式比使用 HttpContext更好。 如果您需要知道目前的 URL 或執行重新導向,則處理的所有轉譯模式的 API NavigationManager 。 如果您需要知道使用者的驗證狀態,請使用 Blazor的服務 AuthenticationStateProvider 來使用 HttpContext.User