Bagikan melalui


Prarender komponen ASP.NET Core Razor

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Artikel ini menjelaskan skenario prarender komponen untuk komponen yang dirender oleh server dalam Razors.

Pra-penyajian adalah proses awalnya merender konten halaman di server tanpa mengaktifkan penanganan aktivitas untuk kontrol yang dirender. Server mengeluarkan UI HTML halaman sesegera mungkin sebagai respons terhadap permintaan awal, yang membuat aplikasi merasa lebih responsif terhadap pengguna. Pra-penyajian juga dapat meningkatkan Pengoptimalan Mesin Pencari (SEO) dengan merender konten untuk respons HTTP awal yang digunakan mesin pencari untuk menghitung peringkat halaman.

Mempertahankan status yang telah dirender sebelumnya

Tanpa mempertahankan status yang telah dirender sebelumnya, status yang digunakan selama pra-penyajian hilang dan harus dibuat ulang saat aplikasi dimuat sepenuhnya. Jika ada keadaan yang dibuat secara asinkron, UI dapat berkedip karena UI yang sudah dirender sebelumnya diganti saat komponen dirender ulang.

Pertimbangkan komponen penghitung berikut PrerenderedCounter1 . Komponen menetapkan nilai penghitung acak awal selama prarender pada metode siklus hidup. Setelah koneksi ke klien dibuat, komponen dirender ulang, dan nilai jumlah awal diganti saat SignalR dijalankan untuk kedua kalinya.

PrerenderedCounter1.razor:

@page "/prerendered-counter-1"
@rendermode @(new InteractiveServerRenderMode(prerender: true))
@inject ILogger<PrerenderedCounter1> Logger

<PageTitle>Prerendered Counter 1</PageTitle>

<h1>Prerendered Counter 1</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount;

    protected override void OnInitialized()
    {
        currentCount = Random.Shared.Next(100);
        Logger.LogInformation("currentCount set to {Count}", currentCount);
    }

    private void IncrementCount() => currentCount++;
}

Jalankan aplikasi dan periksa pengelogan dari komponen. Berikut ini adalah contoh output.

Catatan

Jika aplikasi mengadopsi perutean interaktif dan halaman tersebut dicapai melalui navigasi internal yang ditingkatkan, maka pra-rendering tidak terjadi. Oleh karena itu, Anda harus melakukan pemuatan ulang halaman penuh agar PrerenderedCounter1 komponen dapat melihat output berikut. Untuk informasi selengkapnya, lihat bagian perutean dan prarender interaktif.

info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92

Jumlah pertama yang dicatat terjadi selama prarendering. Jumlah diatur lagi setelah prarender saat komponen dirender. Ada juga kedip di UI ketika hitungan diperbarui dari 41 ke 92.

Untuk mempertahankan nilai awal penghitung selama pra-rendering, Blazor mendukung mempertahankan status di halaman yang sudah dirender sebelumnya menggunakan layanan PersistentComponentState (dan untuk komponen yang disematkan ke dalam halaman atau tampilan Razor halaman atau aplikasi MVC, Tag Helper Status Komponen Persist).

Untuk mempertahankan status yang telah dirender sebelumnya, gunakan [SupplyParameterFromPersistentComponentState] atribut untuk mempertahankan status dalam properti. Properti-properti dengan atribut ini secara otomatis dipertahankan menggunakan layanan PersistentComponentState selama prarendering. Status diambil ketika komponen dirender secara interaktif atau layanan dibuat.

Secara default, properti diserialisasikan menggunakan System.Text.Json serializer dengan pengaturan default. Serialisasi tidak lebih aman dan memerlukan pelestarian jenis yang digunakan. Untuk informasi selengkapnya, lihat Mengonfigurasi Pemangkas untuk ASP.NET Core Blazor.

Komponen penghitung berikut mempertahankan status penghitung selama pra-penyajian dan mengambil status untuk menginisialisasi komponen:

  • Atribut [SupplyParameterFromPersistentComponentState] diterapkan ke CounterState jenis (State).
  • Status penghitung ditetapkan ketika null berada dalam OnInitialized dan status tersebut dipulihkan secara otomatis ketika komponen dirender secara interaktif.

PrerenderedCounter2.razor:

@page "/prerendered-counter-2"
@inject ILogger<PrerenderedCounter2> Logger

<PageTitle>Prerendered Counter 2</PageTitle>

<h1>Prerendered Counter 2</h1>

<p role="status">Current count: @State?.CurrentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    [SupplyParameterFromPersistentComponentState]
    public CounterState? State { get; set; }

    protected override void OnInitialized()
    {
        if (State is null)
        {
            State = new() { CurrentCount = Random.Shared.Next(100) };
            Logger.LogInformation("CurrentCount set to {Count}", 
                State.CurrentCount);
        }
        else
        {
            Logger.LogInformation("CurrentCount restored to {Count}", 
                State.CurrentCount);
        }
    }

    private void IncrementCount()
    {
        if (State is not null)
        {
            State.CurrentCount++;
        }
    }

    public class CounterState
    {
        public int CurrentCount { get; set; }
    }
}

Ketika komponen dijalankan, CurrentCount hanya diatur sekali selama pra-penyajian. Nilai dipulihkan ketika komponen dirender ulang. Berikut ini adalah contoh output.

Catatan

Jika aplikasi mengadopsi perutean interaktif dan halaman tersebut dicapai melalui navigasi internal yang ditingkatkan, maka pra-rendering tidak terjadi. Oleh karena itu, Anda harus melakukan pemuatan ulang halaman penuh agar komponen dapat melihat output berikut. Untuk informasi selengkapnya, lihat bagian perutean dan prarender interaktif.

info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
CurrentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
CurrentCount restored to 96

Dalam contoh berikut yang menserialisasikan status untuk beberapa komponen dengan jenis yang sama:

  • Properti-properti yang dianotasikan dengan atribut [SupplyParameterFromPersistentComponentState] diserialisasi dan dideserialisasi selama prarendering.
  • Atribut@key direktif digunakan untuk memastikan bahwa status dikaitkan dengan instans komponen dengan benar.
  • Properti Element diinisialisasi dalam OnInitialized metode siklus hidup untuk menghindari pengecualian referensi null, mirip dengan bagaimana referensi null dihindari untuk parameter kueri dan data formulir.

PersistentChild.razor:

<div>
    <p>Current count: @Element.CurrentCount</p>
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</div>

@code {
    [SupplyParameterFromPersistentComponentState]
    public State Element { get; set; }

    protected override void OnInitialized()
    {
        Element ??= new State();
    }

    private void IncrementCount()
    {
        Element.CurrentCount++;
    }

    private class State
    {
        public int CurrentCount { get; set; }
    }
}

Parent.razor:

@page "/parent"

@foreach (var element in elements)
{
    <PersistentChild @key="element.Name" />
}

Dalam contoh berikut yang menserialisasikan status untuk layanan injeksi dependensi:

  • Properti yang dianotasikan dengan atribut [SupplyParameterFromPersistentComponentState] diserialisasikan selama proses prarender dan dideserialisasi saat aplikasi aktif.
  • Metode AddPersistentService ini digunakan untuk mendaftarkan layanan untuk persistensi. Mode render diperlukan karena mode render tidak dapat disimpulkan dari jenis layanan. Gunakan salah satu nilai berikut:
    • RenderMode.Server: Layanan ini tersedia untuk mode render Server Interaktif.
    • RenderMode.Webassembly: Layanan ini tersedia untuk mode render Interactive Webassembly.
    • RenderMode.InteractiveAuto: Layanan ini tersedia untuk mode render Interactive Server dan Interactive Webassembly jika komponen dirender di salah satu mode tersebut.
  • Layanan diselesaikan selama inisialisasi mode render interaktif, dan properti yang dianotasi dengan [SupplyParameterFromPersistentComponentState] atribut dideserialisasi.

Catatan

Hanya layanan terlingkup yang bertahan yang didukung.

CounterService.cs:

public class CounterService
{
    [SupplyParameterFromPersistentComponentState]
    public int CurrentCount { get; set; }

    public void IncrementCount()
    {
        CurrentCount++;
    }
}

Dalam Program.cs:

builder.Services.AddPersistentService<CounterService>(RenderMode.InteractiveAuto);

Properti yang diserialkan diidentifikasi dari instance layanan yang sebenarnya.

  • Pendekatan ini memungkinkan menandai abstraksi sebagai layanan persisten.
  • Memungkinkan implementasi yang sebenarnya menjadi internal atau tipe yang berbeda.
  • Mendukung kode yang dibagikan dalam assemblies yang berbeda.
  • Hasil pada setiap instans menunjukkan properti yang sama.

Sebagai alternatif untuk menggunakan model deklaratif untuk mempertahankan status dengan [SupplyParameterFromPersistentComponentState] atribut , Anda dapat menggunakan PersistentComponentState layanan secara langsung, yang menawarkan fleksibilitas yang lebih besar untuk skenario persistensi status yang kompleks. Panggil PersistentComponentState.RegisterOnPersisting untuk mendaftarkan panggilan balik untuk mempertahankan status komponen selama pra-penyajian. Status diambil ketika komponen dirender secara interaktif. Lakukan panggilan pada akhir dari kode inisialisasi untuk menghindari potensi race condition selama pemadaman aplikasi.

Contoh komponen penghitung berikut ini mempertahankan status penghitung selama pra-rendering dan mengambil kembali status tersebut untuk menginisialisasi komponen.

PrerenderedCounter3.razor:

@page "/prerendered-counter-3"
@implements IDisposable
@inject ILogger<PrerenderedCounter3> Logger
@inject PersistentComponentState ApplicationState

<PageTitle>Prerendered Counter 3</PageTitle>

<h1>Prerendered Counter 3</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override void OnInitialized()
    {
        if (!ApplicationState.TryTakeFromJson<int>(
            nameof(currentCount), out var restoredCount))
        {
            currentCount = Random.Shared.Next(100);
            Logger.LogInformation("currentCount set to {Count}", currentCount);
        }
        else
        {
            currentCount = restoredCount!;
            Logger.LogInformation("currentCount restored to {Count}", currentCount);
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
    }

    private Task PersistCount()
    {
        ApplicationState.PersistAsJson(nameof(currentCount), currentCount);

        return Task.CompletedTask;
    }

    private void IncrementCount() => currentCount++;

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}

Ketika komponen dijalankan, currentCount hanya diatur sekali selama pra-penyajian. Nilai dipulihkan ketika komponen dirender ulang. Berikut ini adalah contoh output.

Catatan

Jika aplikasi mengadopsi perutean interaktif dan halaman tersebut dicapai melalui navigasi internal yang ditingkatkan, maka pra-rendering tidak terjadi. Oleh karena itu, Anda harus melakukan pemuatan ulang halaman penuh agar komponen dapat melihat output berikut. Untuk informasi selengkapnya, lihat bagian perutean dan prarender interaktif.

info: BlazorSample.Components.Pages.PrerenderedCounter3[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter3[0]
currentCount restored to 96

Untuk mempertahankan status yang telah dirender sebelumnya, putuskan status apa yang akan bertahan menggunakan PersistentComponentState layanan. PersistentComponentState.RegisterOnPersisting mendaftarkan panggilan balik untuk mempertahankan status komponen selama pra-penyajian. Status diambil ketika komponen dirender secara interaktif. Lakukan panggilan pada akhir dari kode inisialisasi untuk menghindari potensi race condition selama pemadaman aplikasi.

Contoh komponen penghitung berikut ini mempertahankan status penghitung selama pra-rendering dan mengambil kembali status tersebut untuk menginisialisasi komponen.

PrerenderedCounter2.razor:

@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState

<PageTitle>Prerendered Counter 2</PageTitle>

<h1>Prerendered Counter 2</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override void OnInitialized()
    {
        if (!ApplicationState.TryTakeFromJson<int>(
            nameof(currentCount), out var restoredCount))
        {
            currentCount = Random.Shared.Next(100);
            Logger.LogInformation("currentCount set to {Count}", currentCount);
        }
        else
        {
            currentCount = restoredCount!;
            Logger.LogInformation("currentCount restored to {Count}", currentCount);
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
    }

    private Task PersistCount()
    {
        ApplicationState.PersistAsJson(nameof(currentCount), currentCount);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();

    private void IncrementCount() => currentCount++;
}

Ketika komponen dijalankan, currentCount hanya diatur sekali selama pra-penyajian. Nilai dipulihkan ketika komponen dirender ulang. Berikut ini adalah contoh output.

Catatan

Jika aplikasi mengadopsi perutean interaktif dan halaman tersebut dicapai melalui navigasi internal yang ditingkatkan, maka pra-rendering tidak terjadi. Oleh karena itu, Anda harus melakukan pemuatan ulang halaman penuh agar komponen dapat melihat output berikut. Untuk informasi selengkapnya, lihat bagian perutean dan prarender interaktif.

info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96

Dengan menginisialisasi komponen dengan status yang sama yang digunakan selama prarender, langkah-langkah inisialisasi mahal hanya dijalankan sekali. UI yang dirender juga cocok dengan UI yang telah dirender sebelumnya, sehingga tidak ada kedipan yang terjadi di browser.

Status pra-penyajian yang dipertahankan ditransfer ke klien, di mana ia digunakan untuk memulihkan status komponen. Selama penyajian sisi klien (CSR, InteractiveWebAssembly), data diekspos ke browser dan tidak boleh berisi informasi privat yang sensitif. Selama penyajian sisi server interaktif (SSR interaktif, InteractiveServer), Perlindungan Data ASP.NET Core memastikan bahwa data ditransfer dengan aman. Mode InteractiveAuto render menggabungkan interaktivitas WebAssembly dan Server, sehingga perlu untuk mempertimbangkan paparan data ke browser, seperti dalam kasus CSR.

Komponen yang disematkan ke dalam halaman dan tampilan (Razor Pages/MVC)

Untuk komponen yang disematkan ke dalam halaman atau tampilan Razor halaman atau aplikasi MVC, Anda harus menambahkan Pembantu Tag Status Komponen Persist dengan <persist-component-state /> tag HTML di dalam tag penutup </body> tata letak aplikasi. Ini hanya diperlukan untuk Pages dan aplikasi MVC. Untuk informasi selengkapnya, lihat Mempertahankan Pembantu Tag Status Komponen di ASP.NET Core.

Pages/Shared/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

Pemetaan jalur dan pra-rendering interaktif

Saat komponen Routes tidak menentukan mode render, aplikasi menggunakan interaktivitas per halaman/komponen dan navigasi. Menggunakan navigasi per halaman/komponen, navigasi internal† ditangani oleh perutean yang lebih baik setelah aplikasi menjadi interaktif. †Internal dalam konteks ini berarti bahwa tujuan URL dari peristiwa navigasi adalah sebuah titik akhir Blazor yang berada di dalam aplikasi.

Layanan PersistentComponentState hanya berfungsi pada pemuatan awal halaman dan tidak di seluruh peristiwa navigasi halaman internal yang sudah ditingkatkan.

Jika aplikasi melakukan navigasi penuh (tidak ditingkatkan) ke halaman yang menggunakan status komponen persisten, status persisten tersedia untuk digunakan aplikasi saat menjadi interaktif.

Jika sirkuit interaktif telah dibuat dan navigasi yang ditingkatkan dilakukan ke halaman yang menggunakan status komponen persisten, status tidak tersedia di sirkuit yang ada agar komponen dapat menggunakan. Tidak ada perenderan awal untuk permintaan halaman internal, dan layanan PersistentComponentState tidak mengetahui bahwa navigasi yang ditingkatkan telah terjadi. Tidak ada mekanisme untuk mengirimkan pembaruan status ke komponen yang sudah berjalan di sirkuit yang ada. Alasan untuk ini adalah bahwa Blazor hanya mendukung status passing dari server ke klien pada saat runtime menginisialisasi, bukan setelah runtime dimulai.

Pekerjaan tambahan pada kerangka kerja Blazor untuk mengatasi skenario ini sedang dipertimbangkan untuk .NET 10 (November, 2025). Untuk informasi selengkapnya dan diskusi komunitas tentang solusi yang tidak didukung‡, lihat Dukung status komponen persisten di seluruh navigasi halaman yang ditingkatkan (dotnet/aspnetcore #51584). ‡Solusi yang tidak didukung tidak disetujui oleh Microsoft untuk digunakan dalam aplikasi Blazor. Gunakan paket, pendekatan, dan kode pihak ketiga dengan risiko Anda sendiri.

Menonaktifkan navigasi yang ditingkatkan, yang mengurangi performa tetapi juga menghindari masalah status pemuatan halaman dengan PersistentComponentState untuk permintaan halaman internal, dibahas dalam perutean dan navigasi ASP.NET Core Blazor.

Panduan pra-penyajian

Panduan pra-render diatur dalam Blazor dokumentasi berdasarkan topik. Tautan berikut mencakup semua panduan pra-penggambaran di seluruh kumpulan dokumentasi berdasarkan topik:

Untuk .NET 7 atau yang lebih lama, lihat Blazor WebAssembly skenario tambahan keamanan: Pra-penyajian dengan autentikasi. Setelah melihat konten di bagian ini, reset dropdown pemilih versi artikel dokumentasi ke versi rilis .NET terbaru untuk memastikan bahwa halaman dokumentasi dimuat untuk rilis terbaru pada kunjungan berikutnya.