Bagikan melalui


Rakitan beban malas di ASP.NET Core Blazor WebAssembly

Catatan

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

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Blazor WebAssembly performa startup aplikasi dapat ditingkatkan dengan menunggu untuk memuat modul aplikasi yang dibuat oleh pengembang hingga modul tersebut diperlukan, yang disebut pemrosesan lambat.

Bagian awal artikel ini mencakup konfigurasi aplikasi. Untuk demonstrasi yang berfungsi, lihat bagian Contoh lengkap di akhir artikel ini.

Artikel ini hanya berlaku untuk Blazor WebAssembly aplikasi. Pemuatan lambat rakitan tidak menguntungkan aplikasi sisi server karena aplikasi yang dirender oleh server tidak mengunduh rakitan ke klien.

Pemakaian pemuatan malas tidak dianjurkan untuk rakitan inti runtime, yang mungkin akan dipangkas ketika dipublikasikan dan tidak tersedia pada klien saat aplikasi dimuat.

Tempat penampung ekstensi file ({FILE EXTENSION}) untuk file rakitan

File rakitan menggunakan format pengemasan Webcil untuk rakitan .NET dengan ekstensi file .wasm.

Sepanjang artikel, penampung {FILE EXTENSION} mewakili "wasm".

Berkas assembly didasarkan pada Dynamic-Link Libraries (DLL) dengan ekstensi berkas .dll.

Sepanjang artikel, penampung {FILE EXTENSION} mewakili "dll".

Konfigurasi file proyek

Tandai komponen-komponen untuk pemuatan lambat dalam file proyek aplikasi (.csproj) menggunakan item BlazorWebAssemblyLazyLoad. Gunakan nama rakitan dengan ekstensi file. Framework Blazor mencegah assembly dimuat saat peluncuran aplikasi.

<ItemGroup>
  <BlazorWebAssemblyLazyLoad Include="{ASSEMBLY NAME}.{FILE EXTENSION}" />
</ItemGroup>

Penanda {ASSEMBLY NAME} adalah nama assembly, dan penanda {FILE EXTENSION} adalah ekstensi file. Ekstensi file diperlukan.

Sertakan satu BlazorWebAssemblyLazyLoad item untuk setiap rakitan. Jika rangkaian memiliki dependensi, sertakan entri BlazorWebAssemblyLazyLoad untuk setiap dependensi.

Router konfigurasi komponen

Kerangka kerja Blazor mendaftarkan secara otomatis layanan singleton untuk pemuatan tunda rakitan di aplikasi sisi klien Blazor WebAssembly, LazyAssemblyLoader. Metode LazyAssemblyLoader.LoadAssembliesAsync:

  • Menggunakan JS interop untuk mengunduh rakitan melalui panggilan jaringan.
  • Memuat rakitan ke dalam runtime yang dijalankan di WebAssembly di browser.

Catatan

Panduan untuk solusi yang dihosting tercakup dalam bagian "Lazy load assemblies dalam solusi yang dihosting".

Blazor Router Komponen menunjuk rakitan yang Blazor mencari komponen yang dapat dirutekan dan juga bertanggung jawab untuk merender komponen untuk rute tempat pengguna menavigasi. Metode Router pada komponen OnNavigateAsync digunakan bersama dengan pemuatan malas untuk memuat rakitan yang benar untuk titik akhir yang diminta oleh pengguna.

Logika diimplementasikan di dalam OnNavigateAsync untuk menentukan rakitan yang akan dimuat dengan LazyAssemblyLoader. Opsi cara menyusun logika meliputi:

  • Pemeriksaan kondisi di dalam metode OnNavigateAsync.
  • Tabel pencarian yang memetakan rute ke nama rakitan, yang dapat disuntikkan ke komponen atau diimplementasikan dalam kode komponen.

Dalam contoh berikut:

  • Namespace untuk Microsoft.AspNetCore.Components.WebAssembly.Services ditentukan.
  • Layanan LazyAssemblyLoader disuntikkan (AssemblyLoader).
  • Tempat penampung {PATH} adalah jalur di mana daftar rakitan harus dimuat. Contoh ini menggunakan pemeriksaan kondisional untuk memeriksa satu jalur yang memuat satu set rakitan.
  • {LIST OF ASSEMBLIES} placeholder adalah daftar nama file rakitan yang dipisahkan koma, termasuk ekstensi filenya (misalnya, "Assembly1.{FILE EXTENSION}", "Assembly2.{FILE EXTENSION}").

App.razor:

@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="typeof(App).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       [ {LIST OF ASSEMBLIES} ]);
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="typeof(App).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger

<Router AppAssembly="typeof(Program).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

Catatan

Contoh sebelumnya tidak menampilkan konten Router markup komponen Razor (...). Untuk demonstrasi dengan kode lengkap, lihat bagian Contoh lengkap di artikel ini.

Catatan

Dengan rilis .NET 5.0.1 dan untuk rilis 5.x tambahan, Router komponen menyertakan parameter PreferExactMatches diatur ke @true. Untuk informasi selengkapnya, lihat Migrasi dari ASP.NET Core 3.1 ke .NET 5.

Rakitan yang menyertakan komponen yang dapat dirutekan

Ketika daftar rakitan menyertakan komponen yang dapat dirutekan, daftar rakitan untuk jalur tertentu diteruskan ke Router koleksi komponen AdditionalAssemblies .

Dalam contoh berikut:

  • Daftar<Assembly> dalam lazyLoadedAssemblies meneruskan daftar perakitan ke AdditionalAssemblies. Kerangka kerja mencari komponen untuk rute dan memperbarui kumpulan rute jika rute baru ditemukan. Untuk mengakses tipe Assembly, namespace untuk System.Reflection disertakan di bagian atas file App.razor.
  • Tempat penampung {PATH} adalah jalur di mana daftar rakitan harus dimuat. Contoh ini menggunakan pemeriksaan kondisional untuk memeriksa satu jalur yang memuat satu set rakitan.
  • {LIST OF ASSEMBLIES} placeholder adalah daftar nama file rakitan yang dipisahkan koma, termasuk ekstensi filenya (misalnya, "Assembly1.{FILE EXTENSION}", "Assembly2.{FILE EXTENSION}").

App.razor:

@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(App).Assembly" 
    AdditionalAssemblies="lazyLoadedAssemblies" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = [];

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
        {
            if (args.Path == "{PATH}")
            {
                var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                    [ {LIST OF ASSEMBLIES} ]);
                lazyLoadedAssemblies.AddRange(assemblies);
            }
        }
        catch (Exception ex)
        {
            Logger.LogError("Error: {Message}", ex.Message);
        }
    }
}
@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(App).Assembly" 
    AdditionalAssemblies="lazyLoadedAssemblies" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new();

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
        {
            if (args.Path == "{PATH}")
            {
                var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                    new[] { {LIST OF ASSEMBLIES} });
                lazyLoadedAssemblies.AddRange(assemblies);
            }
        }
        catch (Exception ex)
        {
            Logger.LogError("Error: {Message}", ex.Message);
        }
    }
}
@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(Program).Assembly" 
    AdditionalAssemblies="lazyLoadedAssemblies" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new List<Assembly>();

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
           {
               if (args.Path == "{PATH}")
               {
                   var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                       new[] { {LIST OF ASSEMBLIES} });
                   lazyLoadedAssemblies.AddRange(assemblies);
               }
           }
           catch (Exception ex)
           {
               Logger.LogError("Error: {Message}", ex.Message);
           }
    }
}

Catatan

Contoh sebelumnya tidak menampilkan konten Router markup komponen Razor (...). Untuk demonstrasi dengan kode lengkap, lihat bagian Contoh lengkap di artikel ini.

Catatan

Dengan rilis .NET 5.0.1 dan untuk rilis 5.x tambahan, Router komponen menyertakan parameter PreferExactMatches diatur ke @true. Untuk informasi selengkapnya, lihat Migrasi dari ASP.NET Core 3.1 ke .NET 5.

Untuk informasi selengkapnya, lihat Blazor ASP.NET Core.

Interaksi pengguna dengan <Navigating> konten

Saat proses memuat rakitan yang dapat memakan waktu beberapa detik, komponen Router dapat menunjukkan kepada pengguna bahwa transisi halaman sedang terjadi melalui properti Navigating dari router.

Untuk informasi selengkapnya, lihat Blazor ASP.NET Core.

Mengatasi pembatalan di OnNavigateAsync

Objek NavigationContext yang diteruskan ke fungsi panggilan balik OnNavigateAsync berisi CancellationToken yang diatur ketika peristiwa navigasi baru terjadi. Fungsi panggilan balik OnNavigateAsync harus menghasilkan pengecualian ketika token pembatalan diaktifkan untuk menghindari terus menjalankan fungsi panggilan balik OnNavigateAsync pada navigasi yang tidak lagi valid.

Untuk informasi selengkapnya, lihat Blazor ASP.NET Core.

OnNavigateAsync peristiwa dan berkas assembly yang diganti namanya

Pemuat sumber daya bergantung pada nama rakitan yang ditentukan dalam file manifes boot. Jika rakitan diganti namanya, nama rakitan yang digunakan dalam OnNavigateAsync panggilan balik dan nama rakitan dalam file manifes boot tidak sinkron.

Untuk memperbaiki hal ini:

  • Periksa untuk melihat apakah aplikasi berjalan di Production lingkungan saat menentukan nama rakitan mana yang akan digunakan.
  • Simpan nama rakitan yang telah diubah dalam file terpisah dan baca dari file tersebut untuk menentukan nama rakitan yang akan digunakan dengan layanan LazyAssemblyLoader dan panggilan balik OnNavigateAsync.

Rakitan beban malas dalam solusi yang dihosting Blazor WebAssembly

Implementasi pemuatan malas dari kerangka kerja ini mendukung pemuatan malas dengan pra-penyajian dalam Blazor WebAssemblysolusi yang dihosting. Selama prarendering, semua rakitan, termasuk yang ditandai untuk pemuatan lambat, diasumsikan sudah dimuat. Secara manual, daftarkan layanan LazyAssemblyLoader di proyek Server.

Di bagian atas file Program.cs dari proyek Server, tambahkan namespace untuk Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

Dalam Program.cs dari proyek Server, daftarkan layanan:

builder.Services.AddScoped<LazyAssemblyLoader>();

Di bagian atas file Startup.cs dari proyek Server, tambahkan namespace untuk Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

Di dalam proyek Startup.ConfigureServicesStartup.cs (Server), daftarkan layanan:

services.AddScoped<LazyAssemblyLoader>();

Contoh lengkap

Demonstrasi di bagian ini:

  • Membuat rakitan kontrol robot (GrantImaharaRobotControls.{FILE EXTENSION}) sebagai pustaka kelas (Razor RCL) yang menyertakan sebuah komponen (Robot) dengan template jalur (Robot.razor/robot).
  • Lazily memuat assembly RCL untuk merender komponen Robot ketika URL /robot diminta oleh pengguna.

Buat aplikasi mandiri Blazor WebAssembly untuk mendemonstrasikan lazy loading dari assembly perpustakaan kelas. Beri nama proyek LazyLoadTest.

Tambahkan proyek pustaka kelas ASP.NET Core ke solusi:

  • Visual Studio: Klik kanan file solusi di Penjelajah Solusi dan pilih > baru. Dari dialog jenis proyek baru, pilih Razor Library Kelas. Beri nama proyek GrantImaharaRobotControls. Jangan pilih kotak centang Halaman dukungan dan tampilan.
  • Visual Studio Code/.NET CLI: Jalankan dotnet new razorclasslib -o GrantImaharaRobotControls dari prompt perintah. Opsi -o|--output membuat folder dan menamai proyek GrantImaharaRobotControls.

Buat HandGesture kelas di RCL dengan ThumbUp metode yang secara hipotetis membuat robot melakukan gerakan jempol. Metode menerima argumen untuk sumbu, Left atau Right, sebagai enum. Metode ini mengembalikan true ketika berhasil.

HandGesture.cs:

using Microsoft.Extensions.Logging;

namespace GrantImaharaRobotControls;

public static class HandGesture
{
    public static bool ThumbUp(Axis axis, ILogger logger)
    {
        logger.LogInformation("Thumb up gesture. Axis: {Axis}", axis);

        // Code to make robot perform gesture

        return true;
    }
}

public enum Axis { Left, Right }
using Microsoft.Extensions.Logging;

namespace GrantImaharaRobotControls
{
    public static class HandGesture
    {
        public static bool ThumbUp(Axis axis, ILogger logger)
        {
            logger.LogInformation("Thumb up gesture. Axis: {Axis}", axis);

            // Code to make robot perform gesture

            return true;
        }
    }

    public enum Axis { Left, Right }
}

Tambahkan komponen berikut ke akar proyek RCL. Komponen mengizinkan pengguna untuk mengirimkan permintaan gerakan jempol kiri atau kanan.

Robot.razor:

@page "/robot"
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.Extensions.Logging
@inject ILogger<Robot> Logger

<h1>Robot</h1>

<EditForm FormName="RobotForm" Model="robotModel" OnValidSubmit="HandleValidSubmit">
    <InputRadioGroup @bind-Value="robotModel.AxisSelection">
        @foreach (var entry in Enum.GetValues<Axis>())
        {
            <InputRadio Value="entry" />
            <text>&nbsp;</text>@entry<br>
        }
    </InputRadioGroup>

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

<p>
    @message
</p>

@code {
    private RobotModel robotModel = new() { AxisSelection = Axis.Left };
    private string? message;

    private void HandleValidSubmit()
    {
        Logger.LogInformation("HandleValidSubmit called");

        var result = HandGesture.ThumbUp(robotModel.AxisSelection, Logger);

        message = $"ThumbUp returned {result} at {DateTime.Now}.";
    }

    public class RobotModel
    {
        public Axis AxisSelection { get; set; }
    }
}
@page "/robot"
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.Extensions.Logging
@inject ILogger<Robot> Logger

<h1>Robot</h1>

<EditForm Model="robotModel" OnValidSubmit="HandleValidSubmit">
    <InputRadioGroup @bind-Value="robotModel.AxisSelection">
        @foreach (var entry in Enum.GetValues<Axis>())
        {
            <InputRadio Value="entry" />
            <text>&nbsp;</text>@entry<br>
        }
    </InputRadioGroup>

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

<p>
    @message
</p>

@code {
    private RobotModel robotModel = new() { AxisSelection = Axis.Left };
    private string? message;

    private void HandleValidSubmit()
    {
        Logger.LogInformation("HandleValidSubmit called");

        var result = HandGesture.ThumbUp(robotModel.AxisSelection, Logger);

        message = $"ThumbUp returned {result} at {DateTime.Now}.";
    }

    public class RobotModel
    {
        public Axis AxisSelection { get; set; }
    }
}
@page "/robot"
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.Extensions.Logging
@inject ILogger<Robot> Logger

<h1>Robot</h1>

<EditForm Model="robotModel" OnValidSubmit="HandleValidSubmit">
    <InputRadioGroup @bind-Value="robotModel.AxisSelection">
        @foreach (var entry in (Axis[])Enum
            .GetValues(typeof(Axis)))
        {
            <InputRadio Value="entry" />
            <text>&nbsp;</text>@entry<br>
        }
    </InputRadioGroup>

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

<p>
    @message
</p>

@code {
    private RobotModel robotModel = new RobotModel() { AxisSelection = Axis.Left };
    private string message;

    private void HandleValidSubmit()
    {
        Logger.LogInformation("HandleValidSubmit called");

        var result = HandGesture.ThumbUp(robotModel.AxisSelection, Logger);

        message = $"ThumbUp returned {result} at {DateTime.Now}.";
    }

    public class RobotModel
    {
        public Axis AxisSelection { get; set; }
    }
}

Dalam proyek LazyLoadTest, buat referensi proyek untuk GrantImaharaRobotControls RCL:

  • Visual Studio: Klik kanan LazyLoadTest proyek dan pilih Tambahkan>Referensi Proyek untuk menambahkan referensi proyek untuk GrantImaharaRobotControls RCL.
  • Visual Studio Code/.NET CLI: Jalankan dotnet add reference {PATH} dalam shell perintah dari folder proyek. Placeholder {PATH} adalah path ke proyek RCL.

Tentukan rakitan RCL untuk lazy loading dalam LazyLoadTest file proyek aplikasi (.csproj):

<ItemGroup>
    <BlazorWebAssemblyLazyLoad Include="GrantImaharaRobotControls.{FILE EXTENSION}" />
</ItemGroup>

Komponen Router berikut ini menunjukkan proses pemuatan GrantImaharaRobotControls.{FILE EXTENSION} assembly ketika pengguna bernavigasi ke /robot. Ganti komponen default App aplikasi dengan komponen berikut App .

Selama transisi halaman, pesan bergaya ditampilkan kepada pengguna dengan <Navigating> elemen . Untuk informasi selengkapnya, lihat bagian Interaksi pengguna dengan <Navigating> konten .

Perakitan ditugaskan ke AdditionalAssemblies, yang mengakibatkan router mencari perakitan untuk menemukan komponen yang dapat dirutekan, dan menemukan komponen Robot. Rute dari komponen Robot ditambahkan ke dalam koleksi rute aplikasi. Untuk informasi selengkapnya, lihat artikel Blazor dan bagian Rakitan yang mencakup komponen yang dapat dirutekan di artikel ini.

App.razor:

@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(App).Assembly"
        AdditionalAssemblies="lazyLoadedAssemblies" 
        OnNavigateAsync="OnNavigateAsync">
    <Navigating>
        <div style="padding:20px;background-color:blue;color:white">
            <p>Loading the requested page&hellip;</p>
        </div>
    </Navigating>
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = [];
    private bool grantImaharaRobotControlsAssemblyLoaded;

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
        {
            if ((args.Path == "robot") && !grantImaharaRobotControlsAssemblyLoaded)
            {
                var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                    [ "GrantImaharaRobotControls.{FILE EXTENSION}" ]);
                lazyLoadedAssemblies.AddRange(assemblies);
                grantImaharaRobotControlsAssemblyLoaded = true;
            }
        }
        catch (Exception ex)
        {
            Logger.LogError("Error: {Message}", ex.Message);
        }
    }
}
@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(App).Assembly"
        AdditionalAssemblies="lazyLoadedAssemblies" 
        OnNavigateAsync="OnNavigateAsync">
    <Navigating>
        <div style="padding:20px;background-color:blue;color:white">
            <p>Loading the requested page&hellip;</p>
        </div>
    </Navigating>
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new();
    private bool grantImaharaRobotControlsAssemblyLoaded;

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
        {
            if ((args.Path == "robot") && !grantImaharaRobotControlsAssemblyLoaded)
            {
                var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                    new[] { "GrantImaharaRobotControls.{FILE EXTENSION}" });
                lazyLoadedAssemblies.AddRange(assemblies);
                grantImaharaRobotControlsAssemblyLoaded = true;
            }
        }
        catch (Exception ex)
        {
            Logger.LogError("Error: {Message}", ex.Message);
        }
    }
}
@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject ILogger<App> Logger
@inject LazyAssemblyLoader AssemblyLoader

<Router AppAssembly="typeof(Program).Assembly"
        AdditionalAssemblies="lazyLoadedAssemblies" 
        OnNavigateAsync="OnNavigateAsync">
    <Navigating>
        <div style="padding:20px;background-color:blue;color:white">
            <p>Loading the requested page&hellip;</p>
        </div>
    </Navigating>
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

@code {
    private List<Assembly> lazyLoadedAssemblies = new List<Assembly>();
    private bool grantImaharaRobotControlsAssemblyLoaded;

    private async Task OnNavigateAsync(NavigationContext args)
    {
        try
        {
            if ((args.Path == "robot") && !grantImaharaRobotControlsAssemblyLoaded)
            {
                var assemblies = await AssemblyLoader.LoadAssembliesAsync(
                    new[] { "GrantImaharaRobotControls.{FILE EXTENSION}" });
                lazyLoadedAssemblies.AddRange(assemblies);
                grantImaharaRobotControlsAssemblyLoaded = true;
            }
        }
        catch (Exception ex)
        {
            Logger.LogError("Error: {Message}", ex.Message);
        }
    }
}

Buat dan jalankan aplikasi.

Ketika komponen Robot dari RCL diminta di /robot, rakitan GrantImaharaRobotControls.{FILE EXTENSION} dimuat dan komponen Robot diberikan. Anda dapat memeriksa pemuatan komponen di tab Jaringan alat pengembang browser.

Pecahkan masalah

  • Jika penyajian tak terduga terjadi, seperti merender komponen dari navigasi sebelumnya, konfirmasikan bahwa kode melempar jika token pembatalan diatur.
  • Jika assembly yang dikonfigurasi untuk lazy loading secara tak terduga dimuat saat aplikasi dimulai, periksa apakah assembly tersebut ditandai untuk lazy loading dalam file proyek.

Catatan

Masalah yang diketahui ada untuk memuat jenis dari rakitan yang dimuat secara malas. Untuk informasi selengkapnya, lihat Blazor WebAssembly lazy loading assemblies not working when using @ref attribute in the component (dotnet/aspnetcore #29342) .

Sumber Daya Tambahan: