ASP.NET librerie di classi core Razor (RCL) con rendering statico lato server (SSR statico)

Questo articolo fornisce indicazioni per gli autori di librerie di componenti che considerano il supporto per il rendering statico lato server (SSR statico).

Blazorincoraggia lo sviluppo di un ecosistema di librerie di componenti open source e commerciali, denominate Razor formalmente librerie di classi (RCLs). Gli sviluppatori possono anche creare componenti riutilizzabili per condividere i componenti privatamente tra le app all'interno delle proprie aziende. Idealmente, i componenti vengono sviluppati per garantire la compatibilità con il maggior numero possibile di modelli di hosting e modalità di rendering. Ssr statico introduce restrizioni aggiuntive che possono essere più complesse da supportare rispetto alle modalità di rendering interattive.

Comprendere le funzionalità e le restrizioni di SSR statico

Ssr statico è una modalità in cui i componenti vengono eseguiti quando il server gestisce una richiesta HTTP in ingresso. Blazor esegue il rendering del componente come HTML, incluso nella risposta. Dopo l'invio della risposta, lo stato del componente e del renderer sul lato server viene rimosso, quindi tutto ciò che rimane è HTML nel browser.

Il vantaggio di questa modalità è l'hosting più economico, più scalabile, perché non sono necessarie risorse server in corso per mantenere lo stato del componente, non è necessario mantenere alcuna connessione continua tra browser e server e non è necessario alcun payload WebAssembly nel browser.

Per impostazione predefinita, tutti i componenti esistenti possono comunque essere usati con SSR statico. Tuttavia, il costo di questa modalità è che i gestori eventi, ad esempio @onclick†, non possono essere eseguiti per i motivi seguenti:

  • Non è presente alcun codice .NET nel browser per eseguirli.
  • Il server ha immediatamente rimosso qualsiasi stato del componente e del renderer necessario per eseguire gestori eventi o per eseguire nuovamente il ripristino delle stesse istanze del componente.

†E' un'eccezione speciale per il gestore eventi per i @onsubmit moduli, che è sempre funzionale, indipendentemente dalla modalità di rendering.

Questo equivale a come si comportano i componenti durante la pre-esecuzione, prima dell'avvio di un circuito o Blazor WebAssembly di un Blazor runtime.

Per i componenti il cui unico ruolo consiste nel produrre contenuto DOM di sola lettura, questi comportamenti per SSR statici sono completamente sufficienti. Tuttavia, gli autori di librerie devono prendere in considerazione l'approccio da adottare quando si includono componenti interattivi nelle rispettive librerie.

Opzioni per gli autori di componenti

Esistono tre approcci principali:

  • Non usare comportamenti interattivi (Basic)

    Per i componenti il cui unico ruolo consiste nel produrre contenuto DOM di sola lettura, lo sviluppatore non deve eseguire alcuna azione speciale. Questi componenti funzionano naturalmente con qualsiasi modalità di rendering.

    Esempi:

    • Componente "scheda utente" che carica i dati corrispondenti a una persona e ne esegue il rendering in un'interfaccia utente stilizzata con una foto, un titolo di lavoro e altri dettagli.
    • Un componente "video" che funge da wrapper intorno all'elemento HTML <video> , rendendo più pratico l'uso in un Razor componente.
  • Richiedi rendering interattivo (Basic)

    È possibile scegliere di richiedere che il componente venga usato solo con il rendering interattivo. Questo limita l'applicabilità del componente, ma significa che è possibile basarsi liberamente su gestori di eventi arbitrari. Anche in questo caso, è comunque consigliabile evitare di dichiarare un elemento specifico @rendermode e consentire all'autore dell'app che utilizza la libreria di selezionare uno.

    Esempi:

    • Componente di modifica video in cui gli utenti possono complice e riordinare segmenti di video. Anche se c'era un modo per rappresentare queste operazioni di modifica con semplici pulsanti HTML e post di modulo, l'esperienza utente sarebbe inaccettabile senza vera interattività.
    • Editor di documenti collaborativo che deve mostrare le attività di altri utenti in tempo reale.
  • Usare comportamenti interattivi, ma progettare per ssri statici e miglioramenti progressivi (avanzate)

    È possibile implementare molti comportamenti interattivi usando solo le funzionalità HTML. Con una buona conoscenza di HTML e CSS, spesso è possibile produrre una baseline utile di funzionalità che funziona con SSR statico. È comunque possibile dichiarare gestori eventi che implementano comportamenti più avanzati e facoltativi, che funzionano solo nelle modalità di rendering interattive.

    Esempi:

    • Componente griglia. In SSR statico, il componente può supportare solo la visualizzazione dei dati e lo spostamento tra le pagine (implementate con <a> i collegamenti). Se usato con il rendering interattivo, il componente può aggiungere l'ordinamento e il filtro in tempo reale.
    • Componente del set di tabulazioni. Finché lo spostamento tra le schede viene ottenuto usando <a> i collegamenti e lo stato viene mantenuto solo nei parametri di query URL, il componente può funzionare senza @onclick.
    • Componente di caricamento di file avanzato. In SSR statico, il componente può comportarsi come nativo <input type=file>. Se usato con il rendering interattivo, il componente potrebbe anche visualizzare lo stato di avanzamento del caricamento.
    • Un ticker azionario. In SSR statico, il componente può visualizzare l'offerta azionaria al momento del rendering del codice HTML. Se usato con il rendering interattivo, il componente può quindi aggiornare il prezzo azionario in tempo reale.

Per una di queste strategie, è anche possibile implementare funzionalità interattive con JavaScript.

Per scegliere tra questi approcci, gli autori di componenti riutilizzabili Razor devono fare un compromesso sui costi/benefici. Il componente è più utile e ha una base utente più ampia se supporta tutte le modalità di rendering, incluso SSR statico. Tuttavia, è necessario più lavoro per progettare e implementare un componente che supporta e sfrutta al meglio ogni modalità di rendering.

Quando usare la @rendermode direttiva

Nella maggior parte dei casi, gli autori di componenti riutilizzabili non devono specificare una modalità di rendering, anche quando è necessaria l'interattività. Ciò è dovuto al fatto che l'autore del componente non sa se l'app abilita il supporto per InteractiveServer, InteractiveWebAssemblyo entrambi con InteractiveAuto. Non specificando un elemento @rendermode, l'autore del componente lascia la scelta allo sviluppatore dell'app.

Anche se l'autore del componente ritiene che sia necessaria l'interattività, potrebbero essere presenti casi in cui un autore dell'app lo considera sufficiente per usare solo SSR statico. Ad esempio, un componente della mappa con interattività di trascinamento e zoom potrebbe richiedere interattività. Tuttavia, alcuni scenari possono chiamare solo per il rendering di un'immagine mappa statica ed evitare funzionalità di trascinamento/zoom.

L'unico motivo per cui un autore di componenti riutilizzabile deve usare la @rendermode direttiva sul relativo componente è se l'implementazione è fondamentalmente associata a una modalità di rendering specifica e provocherebbe certamente un errore se usato in una modalità diversa. Si consideri un componente con lo scopo principale di interagire direttamente con il sistema operativo host usando API specifiche di Windows o Linux. Potrebbe essere impossibile usare tale componente in WebAssembly. In tal caso, è ragionevole dichiarare @rendermode InteractiveServer per il componente.

Rendering in streaming

I componenti riutilizzabili Razor sono gratuiti per dichiarare @attribute [StreamRendering] per il rendering in streaming ([StreamRendering] API attributo). Ciò comporta aggiornamenti incrementali dell'interfaccia utente durante ssr statici. Poiché gli stessi modelli di caricamento dei dati producono aggiornamenti incrementali dell'interfaccia utente durante il rendering interattivo, indipendentemente dalla presenza dell'attributo [StreamRendering] , il componente può comportarsi correttamente in tutti i casi. Anche nei casi in cui lo streaming statico di SSR viene eliminato nel server, il componente esegue comunque il rendering dello stato finale corretto.

I componenti riutilizzabili Razor possono usare collegamenti e spostamento avanzato. I tag HTML <a> devono produrre comportamenti equivalenti con o senza un componente interattivo Router e se la navigazione avanzata è abilitata/disabilitata a livello di predecessore nel DOM.

Uso dei moduli tra le modalità di rendering

I componenti riutilizzabili Razor possono includere moduli ( <form> o <EditForm>), perché possono essere implementati per funzionare in modo equivalente nelle modalità di rendering statiche e interattive.

Si consideri l'esempio seguente:

<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()
    {
        ...
    }
}

Le EnhanceAPI , FormNamee SupplyParameterFromFormAttribute vengono usate solo durante il ssr statico e vengono ignorate durante il rendering interattivo. Il modulo funziona correttamente durante ssri interattivi e statici.

Evitare API specifiche di SSR statico

Per rendere un componente riutilizzabile che funziona in tutte le modalità di rendering, non basarsi su HttpContext perché è disponibile solo durante la ssr statica. L'API HttpContext non ha senso usare durante il rendering interattivo perché non esiste alcuna richiesta HTTP attiva in anteprima in tali momenti. È inutile pensare all'impostazione di un codice di stato o alla scrittura nella risposta.

I componenti riutilizzabili sono liberi di ricevere un oggetto HttpContext quando disponibile, come indicato di seguito:

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

Il valore è null durante il rendering interattivo e viene impostato solo durante il ssr statico.

In molti casi, esistono alternative migliori rispetto all'uso HttpContextdi . Se è necessario conoscere l'URL corrente o eseguire un reindirizzamento, le API in NavigationManager uso con tutte le modalità di rendering. Se è necessario conoscere lo stato di autenticazione dell'utente, usare il Blazorservizio tramite AuthenticationStateProviderHttpContext.User.