Udostępnij za pośrednictwem


Leniwe ładowanie zestawów w ASP.NET Core Blazor WebAssembly

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.

Blazor WebAssembly Wydajność uruchamiania aplikacji można poprawić, czekając na załadowanie zestawów aplikacji utworzonych przez deweloperów, dopóki zestawy nie będą wymagane, co jest nazywane ładowaniem leniwym.

W pierwszych sekcjach tego artykułu omówiono konfigurację aplikacji. Aby zapoznać się z pokazem roboczym, zobacz sekcję Kompletny przykład na końcu tego artykułu.

Ten artykuł dotyczy tylko aplikacji Blazor WebAssembly. Ładowanie zestawów z opóźnieniem nie przynosi korzyści aplikacjom po stronie serwera, ponieważ aplikacje renderowane na serwerze nie pobierają zestawów do klienta.

Leniwe ładowanie nie powinno być używane w przypadku podstawowych zestawów środowiska uruchomieniowego, które mogą być przycinane podczas publikowania i niedostępne dla klienta podczas ładowania aplikacji.

Symbol zastępczy rozszerzenia pliku ({FILE EXTENSION}) dla plików kompilacji

Pliki zestawów używają formatu pakietowania Webcil dla zestawów .NET z rozszerzeniem pliku .

W całym artykule symbol zastępczy {FILE EXTENSION} oznacza "wasm".

Pliki zestawów są oparte na bibliotekach łącza dynamicznego (DLL) z rozszerzeniem pliku .dll.

W całym artykule symbol zastępczy {FILE EXTENSION} oznacza "dll".

Konfiguracja pliku projektu

Oznacz zestawy do ładowania z opóźnieniem w pliku projektu aplikacji (.csproj) przy użyciu pozycji BlazorWebAssemblyLazyLoad. Użyj nazwy zestawu z rozszerzeniem pliku. Platforma Blazor uniemożliwia ładowanie zestawu podczas uruchamiania aplikacji.

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

Symbol {ASSEMBLY NAME} zastępczy to nazwa zestawu, a {FILE EXTENSION} symbol zastępczy to rozszerzenie pliku. Rozszerzenie pliku jest wymagane.

Uwzględnij jeden BlazorWebAssemblyLazyLoad element dla każdego zestawu. Jeśli zestaw ma zależności, dołącz BlazorWebAssemblyLazyLoad wpis dla każdej zależności.

Router konfiguracja składnika

Platforma Blazor automatycznie rejestruje usługę singleton do leniwego ładowania zestawów w aplikacjach po stronie klienta Blazor WebAssembly, LazyAssemblyLoader. Metoda LazyAssemblyLoader.LoadAssembliesAsync:

  • Używa JS międzyoperacyjności do pobierania zestawów za pośrednictwem wywołania sieciowego.
  • Ładuje zestawy do środowiska wykonawczego działającego na WebAssembly w przeglądarce.

Uwaga

Wskazówki dotyczące hostowanychBlazor WebAssemblyrozwiązań zostały omówione w sekcji Lazy load assemblies in a hosted Blazor WebAssembly solution.

Blazor składnik Router wyznacza zestawy, które Blazor przeszukuje w poszukiwaniu komponowalnych składników i odpowiada za renderowanie składnika na trasie, po której nawigują użytkownicy. Router komponentu metodaOnNavigateAsync jest używana w połączeniu z ładowaniem leniwym w celu załadowania poprawnych zestawów dla punktów końcowych żądanych przez użytkownika.

Logika jest zaimplementowana wewnątrz OnNavigateAsync, aby określić zestawy do załadowania za pomocą LazyAssemblyLoader polecenia. Opcje struktury logiki obejmują:

  • Testy warunkowe wewnątrz metody OnNavigateAsync.
  • Tabela odnośników, która mapuje trasy na nazwy zestawów, wprowadzone do składnika lub zaimplementowane w kodzie składnika.

W poniższym przykładzie:

  • Przestrzeń nazw Microsoft.AspNetCore.Components.WebAssembly.Services została określona.
  • Usługa LazyAssemblyLoader jest wstrzykiwana (AssemblyLoader).
  • Symbol zastępczy {PATH} oznacza ścieżkę, gdzie powinna być załadowana lista zestawów. W przykładzie użyto sprawdzania warunkowego dla pojedynczej ścieżki, która ładuje pojedynczy zestaw.
  • Symbol zastępczy {LIST OF ASSEMBLIES} to lista ciągów nazw plików zestawu rozdzielonych przecinkami, zawierająca ich rozszerzenia plików (na przykład "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);
           }
    }
}

Uwaga

W poprzednim przykładzie nie jest pokazana zawartość markupowa składnika RouterRazor (...). Aby zapoznać się z pokazem z pełnym kodem, zobacz sekcję Kompletny przykład tego artykułu.

Uwaga

Wraz z wydaniem platformy .NET 5.0.1 i wszystkimi dodatkowymi wersjami 5.x składnik zawiera parametr Router ustawiony na wartość PreferExactMatches. Aby uzyskać więcej informacji, zobacz Migrowanie z platformy ASP.NET Core 3.1 do platformy .NET 5.

Zestawy zawierające komponenty routowalne

Gdy lista zestawów zawiera składniki routingu, wówczas lista zestawów dla danej ścieżki jest przekazywana do kolekcji składnika RouterAdditionalAssemblies.

W poniższym przykładzie:

  • Lista <Assembly> w lazyLoadedAssemblies przekazuje listę zestawów do AdditionalAssemblies. Platforma wyszukuje zestawy tras i aktualizuje kolekcję tras, jeśli zostaną znalezione nowe trasy. Aby uzyskać dostęp do typu Assembly, przestrzeń nazw dla System.Reflection jest dołączona na górze pliku App.razor.
  • Symbol zastępczy {PATH} oznacza ścieżkę, gdzie powinna być załadowana lista zestawów. W przykładzie użyto sprawdzania warunkowego dla pojedynczej ścieżki, która ładuje pojedynczy zestaw.
  • Symbol zastępczy {LIST OF ASSEMBLIES} to lista ciągów nazw plików zestawu rozdzielonych przecinkami, zawierająca ich rozszerzenia plików (na przykład "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);
           }
    }
}

Uwaga

W poprzednim przykładzie nie jest pokazana zawartość markupowa składnika RouterRazor (...). Aby zapoznać się z pokazem z pełnym kodem, zobacz sekcję Kompletny przykład tego artykułu.

Uwaga

Wraz z wydaniem platformy .NET 5.0.1 i wszystkimi dodatkowymi wersjami 5.x składnik zawiera parametr Router ustawiony na wartość PreferExactMatches. Aby uzyskać więcej informacji, zobacz Migrowanie z platformy ASP.NET Core 3.1 do platformy .NET 5.

Aby uzyskać więcej informacji, zobacz trasowanie i nawigację w ASP.NET Core Blazor.

Interakcja użytkownika z zawartością <Navigating>

Podczas ładowania zestawów, co może potrwać kilka sekund, składnik Router może wskazać użytkownikowi, że przejście strony odbywa się za pomocą właściwości routera Navigating.

Aby uzyskać więcej informacji, zobacz trasowanie i nawigację w ASP.NET Core Blazor.

Obsługa anulowań w OnNavigateAsync

Obiekt NavigationContext przekazany do wywołania zwrotnego OnNavigateAsync zawiera element CancellationToken, który jest ustawiany, gdy wystąpi nowe zdarzenie nawigacji. Wywołanie OnNavigateAsync zwrotne musi zgłosić, gdy token anulowania jest ustawiony, aby uniknąć dalszego wykonywania OnNavigateAsync wywołania zwrotnego na nieaktualnej nawigacji.

Aby uzyskać więcej informacji, zobacz trasowanie i nawigację w ASP.NET Core Blazor.

OnNavigateAsync zdarzenia i pliki zestawów o zmienionej nazwie

Moduł ładujący zasobów opiera się na nazwach zestawów zdefiniowanych w pliku manifestu rozruchu. Jeśli nazwy zestawów zostaną zmienione, nazwy zestawów używane w wywołaniu zwrotnym OnNavigateAsync i nazwy zestawów w pliku manifestu rozruchu nie są zsynchronizowane.

Aby rozwiązać ten problem:

  • Sprawdź, czy aplikacja jest uruchomiona w Production środowisku, aby określić, jakich nazw zestawów użyć.
  • Zapisz zmienione nazwy assembly w osobnym pliku, a następnie odczytaj z tego pliku, aby określić, jakiej nazwy assembly użyć z usługą LazyAssemblyLoader i wywołaniem zwrotnym OnNavigateAsync.

Ładowanie zestawów z opóźnieniem w rozwiązaniu hostowanym Blazor WebAssembly

Implementacja ładowania z opóźnieniem platformy obsługuje ładowanie z opóźnieniem z prerenderingiem w rozwiązaniu hostowanym.Blazor WebAssembly Podczas prerenderingu przyjmuje się, że wszystkie zestawy, w tym te oznaczone do ładowania leniwego, mają zostać załadowane. Ręcznie zarejestruj usługę LazyAssemblyLoader w projekcie Server .

Na początku pliku Program.cs projektu Server dodaj przestrzeń nazw dla Microsoft.AspNetCore.Components.WebAssembly.Services.

using Microsoft.AspNetCore.Components.WebAssembly.Services;

W Program.cs projekcie Server zarejestruj usługę:

builder.Services.AddScoped<LazyAssemblyLoader>();

Na początku pliku Startup.cs projektu Server dodaj przestrzeń nazw dla Microsoft.AspNetCore.Components.WebAssembly.Services.

using Microsoft.AspNetCore.Components.WebAssembly.Services;

W Startup.ConfigureServices (Startup.cs) Server projektu zarejestruj usługę:

services.AddScoped<LazyAssemblyLoader>();

Kompletny przykład

Demonstracja w tej sekcji:

  • Tworzy zestaw kontrolek robota (GrantImaharaRobotControls.{FILE EXTENSION}) jako bibliotekę klasy Razor (RCL), która zawiera składnik Robot (Robot.razor z szablonem trasy /robot).
  • Leniwie ładuje zestaw RCL w celu renderowania jego Robot składnika, gdy użytkownik zażąda adresu URL /robot.

Utwórz samodzielną Blazor WebAssembly aplikację, aby zademonstrować leniwe ładowanie zestawu biblioteki klas Razor. Nadaj projektowi LazyLoadTestnazwę .

Dodaj projekt biblioteki klas ASP.NET Core do rozwiązania:

  • Visual Studio: kliknij prawym przyciskiem myszy plik rozwiązania w Eksploratorze rozwiązań i wybierz Dodaj>Nowy projekt. W oknie dialogowym nowych typów projektów wybierz pozycję Razor Biblioteka klas. Nadaj projektowi GrantImaharaRobotControlsnazwę . Nie zaznaczaj pola wyboru Strony i widoki pomocy technicznej.
  • Visual Studio Code/.NET CLI: uruchom dotnet new razorclasslib -o GrantImaharaRobotControls w wierszu polecenia. Opcja -o|--output tworzy folder i nada projektowi GrantImaharaRobotControlsnazwę .

Utwórz klasę HandGesture na liście RCL za pomocą ThumbUp metody, która hipotetycznie sprawia, że robot wykonuje gest kciuka w górę. Metoda akceptuje argument osi Left lub Right, jako enum. Metoda zwraca true w przypadku powodzenia.

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 }
}

Dodaj następujący składnik do katalogu głównego projektu RCL. Składnik umożliwia użytkownikowi przesłanie żądania gestu podniesienia kciuka lewą lub prawą ręką.

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; }
    }
}

W projekcie LazyLoadTest utwórz odwołanie do projektu GrantImaharaRobotControls RCL.

  • Visual Studio: kliknij prawym przyciskiem myszy projekt LazyLoadTest i wybierz Dodaj>odwołanie do projektu, aby dodać odwołanie do projektu GrantImaharaRobotControls RCL.
  • Visual Studio Code/.NET CLI: wykonaj polecenie dotnet add reference {PATH} w interfejsie wiersza poleceń z folderu projektu. Symbol {PATH} zastępczy to ścieżka do projektu RCL.

Określ zestaw RCL na potrzeby leniwego ładowania w pliku projektu aplikacji LazyLoadTest (.csproj):

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

Poniższy Router składnik demonstruje ładowanie GrantImaharaRobotControls.{FILE EXTENSION} zestawu, gdy użytkownik przejdzie do /robot elementu. Zastąp domyślny App składnik aplikacji następującym App składnikiem.

Podczas przechodzenia strony wyświetlany jest użytkownikowi stylizowany komunikat z elementem <Navigating> . Aby uzyskać więcej informacji, zobacz sekcję Interakcja użytkownika z zawartością<Navigating>.

Zestaw jest przypisywany do AdditionalAssemblies, co powoduje przeszukiwanie zestawu w poszukiwaniu elementów routingu, gdzie znajduje element Robot. Trasa Robot składnika jest dodawana do kolekcji tras aplikacji. Aby uzyskać więcej informacji, zobacz artykuł o routingu i nawigacji w ASP.NET CoreBlazor oraz sekcję Zestawy zawierające routowalne składniki w tym artykule.

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);
        }
    }
}

Skompiluj i uruchom aplikację.

Gdy składnik Robot z RCL jest żądany na /robot, zestaw GrantImaharaRobotControls.{FILE EXTENSION} jest ładowany, a składnik Robot jest renderowany. Ładowanie zestawu można sprawdzić na karcie Sieć w narzędziach deweloperskich przeglądarki.

Rozwiązywanie problemów

  • Jeśli wystąpi nieoczekiwane renderowanie, takie jak renderowanie składnika z poprzedniej nawigacji, upewnij się, że kod zgłasza błąd, jeśli token anulowania został ustawiony.
  • Jeśli zestawy skonfigurowane do leniwego ładowania niespodziewanie ładują się podczas uruchamiania aplikacji, sprawdź, czy zestaw jest oznaczony do leniwego ładowania w pliku projektu.

Uwaga

Istnieje znany problem dotyczący ładowania typów z zestawu załadowanego z opóźnieniem. Aby uzyskać więcej informacji, zobacz Blazor WebAssembly lazy loading assemblies not working when using @ref attribute in the component (dotnet/aspnetcore #29342).

Dodatkowe zasoby