Dela via


Fördröjd inläsning av samlingar i ASP.NET Core Blazor WebAssembly

Anmärkning

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Viktigt!

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Blazor WebAssembly Appens startprestanda kan förbättras genom att vänta med att läsa in av utvecklare skapade appsamlingar tills samlingarna behövs, vilket kallas lätt inläsning.

Den här artikelns första avsnitt beskriver appkonfigurationen. En fungerande demonstration finns i avsnittet Fullständigt exempel i slutet av den här artikeln.

Den här artikeln gäller endast för Blazor WebAssembly appar. Sammansättningens lata inläsning gynnar inte appar på serversidan eftersom server renderade appar inte laddar ned sammansättningar till klienten.

Lat inläsning ska inte användas för kärnkörningssammansättningar, som kan trimmas vid publicering och otillgänglig på klienten när appen läses in.

Platshållare för filnamnstillägg ({FILE EXTENSION}) för sammansättningsfiler

Sammansättningsfiler använder webcilpaketeringsformatet för .NET-sammansättningar med ett .wasm filnamnstillägg.

I artikeln {FILE EXTENSION} representerar platshållaren "wasm".

Sammansättningsfiler baseras på Dynamic-Link bibliotek (DLL: er) med ett .dll filnamnstillägg.

I artikeln {FILE EXTENSION} representerar platshållaren "dll".

Projektfilkonfiguration

Markera sammansättningar för lat inläsning i appens projektfil (.csproj) med hjälp av BlazorWebAssemblyLazyLoad objektet. Använd assemblénamnet med filnamnstillägget. Ramverket Blazor förhindrar att sammansättningen läses in vid appstart.

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

Platshållaren {ASSEMBLY NAME} är namnet på programsamlingen och platshållaren {FILE EXTENSION} är filtillägget. Filnamnstillägget krävs.

Inkludera ett BlazorWebAssemblyLazyLoad objekt för varje sammansättning. Om en sammansättning har beroenden inkluderar du en BlazorWebAssemblyLazyLoad post för varje beroende.

Router komponentkonfiguration

Ramverket Blazor registrerar automatiskt en singleton-tjänst för lazy loading-samlingar i klientsideappar Blazor WebAssembly, LazyAssemblyLoader. LazyAssemblyLoader.LoadAssembliesAsync-metoden:

  • Använder JS interop för att hämta sammansättningar via ett nätverksanrop.
  • Läser in assemblies till runtime-miljön som exekveras på WebAssembly i webbläsaren.

Anmärkning

Vägledning för värdbaseradeBlazor WebAssemblylösningar finns i avsnittet Lazy load-sammansättningar i en värdbaserad Blazor WebAssembly lösning.

BlazorKomponenten Router anger de sammansättningar som Blazor söker efter dirigerbara komponenter och ansvarar även för att återge komponenten för den väg där användaren navigerar. Komponentens RouterOnNavigateAsync metod används tillsammans med lat inläsning för att läsa in rätt sammansättningar för slutpunkter som en användare begär.

Logik implementeras inuti OnNavigateAsync för att fastställa vilka sammansättningar som ska läsas in med LazyAssemblyLoader. Alternativ för hur du strukturerar logiken är:

  • Villkorsstyrda kontroller i OnNavigateAsync metoden.
  • En uppslagstabell som mappar vägar till sammansättningsnamn, antingen inmatade i komponenten eller implementerade i komponentens kod.

I följande exempel:

  • Namnområdet för Microsoft.AspNetCore.Components.WebAssembly.Services har angetts.
  • Tjänsten LazyAssemblyLoader matas in (AssemblyLoader).
  • Platshållaren {PATH} är den sökväg där listan över sammansättningar ska läsas in. I exemplet används en villkorsstyrd kontroll av en enskild sökväg som läser in en enda uppsättning sammansättningar.
  • Platshållaren {LIST OF ASSEMBLIES} är den kommaavgränsade listan över sammansättningsfilnamnssträngar, inklusive deras filnamnstillägg (till exempel "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);
           }
    }
}

Anmärkning

Föregående exempel visar inte innehållet i komponentens RouterRazor markering (...). En demonstration med fullständig kod finns i avsnittet Fullständigt exempel i den här artikeln.

Anmärkning

Med versionen av .NET 5.0.1 och för ytterligare 5.x-versioner innehåller komponenten Router parametern PreferExactMatches inställd på @true. Mer information finns i Migrera från ASP.NET Core 3.1 till .NET 5.

Sammansättningar som innehåller dirigerbara komponenter

När listan över sammansättningar innehåller dirigerbara komponenter skickas sammansättningslistan för en viss sökväg till komponentens RouterAdditionalAssemblies samling.

I följande exempel:

  • Listan<Assembly> i lazyLoadedAssemblies överför monteringslistan till AdditionalAssemblies. Ramverket söker i sammansättningarna efter vägar och uppdaterar routningssamlingen om nya vägar hittas. För att komma åt Assembly typen inkluderas namnområdet för System.Reflection överst i App.razor filen.
  • Platshållaren {PATH} är den sökväg där listan över sammansättningar ska läsas in. I exemplet används en villkorsstyrd kontroll av en enskild sökväg som läser in en enda uppsättning sammansättningar.
  • Platshållaren {LIST OF ASSEMBLIES} är den kommaavgränsade listan över sammansättningsfilnamnssträngar, inklusive deras filnamnstillägg (till exempel "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);
           }
    }
}

Anmärkning

Föregående exempel visar inte innehållet i komponentens RouterRazor markering (...). En demonstration med fullständig kod finns i avsnittet Fullständigt exempel i den här artikeln.

Anmärkning

Med versionen av .NET 5.0.1 och för ytterligare 5.x-versioner innehåller komponenten Router parametern PreferExactMatches inställd på @true. Mer information finns i Migrera från ASP.NET Core 3.1 till .NET 5.

Mer information finns i ASP.NET Core Blazor routning och navigering.

Användarinteraktion med <Navigating> innehåll

När sammansättningar läses in, vilket kan ta flera sekunder, kan komponenten Router indikera för användaren att en sidövergång sker med routerns Navigating egenskap.

Mer information finns i ASP.NET Core Blazor routning och navigering.

Hantera annulleringar i OnNavigateAsync

Det NavigationContext-objekt som skickas till OnNavigateAsync callback innehåller en CancellationToken som anges vid en ny navigeringshändelse. Återanropet OnNavigateAsync måste kastas när annulleringstoken är inställd för att undvika att fortsätta köra återanropet OnNavigateAsync vid en inaktuell navigering.

Mer information finns i ASP.NET Core Blazor routning och navigering.

OnNavigateAsync händelser och omdöpta sammansättningsfiler

Resursinläsaren förlitar sig på de sammansättningsnamn som definieras i startmanifestfilen. Om sammansättningar byts namn är de sammansättningsnamn som används i ett OnNavigateAsync återanrop och sammansättningsnamnen i startmanifestfilen inte synkroniserade.

Så här åtgärdar du detta:

  • Kontrollera om appen körs i Production miljön när du avgör vilka sammansättningsnamn som ska användas.
  • Lagra de omdöpta sammansättningsnamnen i en separat fil och läs från den filen för att avgöra vilket sammansättningsnamn som ska användas med LazyAssemblyLoader tjänsten och OnNavigateAsync återanropet.

Lazy load-sammansättningar i en värdbaserad Blazor WebAssembly lösning

Ramverkets implementering av lat inläsning stöder lat inläsning med prerendering i en värdbaserad Blazor WebAssemblylösning. Under förgenereringen antas alla sammansättningar, inklusive de som har markerats för lat laddning, laddas in. Registrera LazyAssemblyLoader tjänsten manuellt i Server projektet.

Överst i Program.cs filen i Server projektet lägger du till namnområdet för Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

I Program.cs projektet Server registrerar du tjänsten:

builder.Services.AddScoped<LazyAssemblyLoader>();

Överst i Startup.cs filen i Server projektet lägger du till namnområdet för Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

I Startup.ConfigureServices (Startup.cs) i Server projektet registrerar du tjänsten:

services.AddScoped<LazyAssemblyLoader>();

Fullständigt exempel

Demonstrationen i det här avsnittet:

  • Skapar en robot som styr sammansättning (GrantImaharaRobotControls.{FILE EXTENSION}) som ett Razor klassbibliotek (RCL) som innehåller en Robot komponent (Robot.razor med en routningsmall på /robot).
  • Laddar in långsamt RCL-sammansättningen för att rendera dess Robot-komponent när /robot-URL:en begärs av användaren.

Skapa en fristående Blazor WebAssembly app för att demonstrera lat inläsning av ett Razor klassbiblioteks sammansättning. Ge projektet namnet LazyLoadTest.

Lägg till ett ASP.NET Core-klassbiblioteksprojekt i lösningen:

  • Visual Studio: Högerklicka på lösningsfilen i Solution Explorer och välj Lägg till>nytt projekt. I dialogrutan med nya projekttyper väljer du Razor Klassbibliotek. Ge projektet namnet GrantImaharaRobotControls. Markera inte kryssrutan Supportsidor och vyer.
  • Visual Studio Code/.NET CLI: Kör dotnet new razorclasslib -o GrantImaharaRobotControls från en kommandoprompt. Alternativet -o|--output skapar en mapp och ger projektet GrantImaharaRobotControlsnamnet .

Skapa en HandGesture klass i RCL med en ThumbUp metod som hypotetiskt får en robot att utföra en tummen upp-gest. Metoden accepterar ett argument för axeln, Left eller Right, som en enum. Metoden returnerar true vid lyckat resultat.

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

Lägg till följande komponent i roten för RCL-projektet. Komponenten tillåter användaren att skicka en begäran om en tumme upp-gest med vänster eller höger hand.

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

LazyLoadTest I projektet skapar du en projektreferens för GrantImaharaRobotControls RCL:

  • Visual Studio: Högerklicka på LazyLoadTest projektet och välj Lägg till>projektreferens för att lägga till en projektreferens för GrantImaharaRobotControls RCL.
  • Visual Studio Code/.NET CLI: Kör dotnet add reference {PATH} i ett kommandogränssnitt från projektets mapp. Platshållaren {PATH} är sökvägen till RCL-projektet.

Ange RCL:s sammansättning för lat inläsning i LazyLoadTest appens projektfil (.csproj):

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

Följande Router komponent demonstrerar laddningen av GrantImaharaRobotControls.{FILE EXTENSION} assembly när användaren navigerar till /robot. Ersätt appens standardkomponent App med följande App komponent.

Under sidövergångar visas ett formaterat meddelande för användaren med elementet <Navigating> . Mer information finns i avsnittet Användarinteraktion med <Navigating> innehåll .

Sammansättningen tilldelas AdditionalAssemblies, vilket resulterar i att routern söker i sammansättningen efter routningsbara komponenter, där den hittar Robot-komponenten. Komponentens Robot väg läggs till i appens vägsamling. Mer information finns i artikeln ASP.NET Core-routning Blazor och navigering samt avsnittet Sammansättningar som innehåller routningsbara komponenter i den här artikeln.

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

Skapa och kör appen.

När komponenten Robot från RCL begärs på /robot, läses samlingen GrantImaharaRobotControls.{FILE EXTENSION} in och komponenten Robot renderas. Du kan granska sammansättningsinläsningen på fliken Nätverk i webbläsarens utvecklarverktyg.

Felsökning

  • Om oväntad återgivning inträffar, till exempel om en komponent återges från en tidigare navigering, bekräftar du att koden genererar om annulleringstoken har angetts.
  • Om sammansättningar som konfigurerats för lat inläsning oväntat läses in vid appstart kontrollerar du att sammansättningen har markerats för lat inläsning i projektfilen.

Anmärkning

Det finns ett känt problem för inläsning av typer från en försiktigt inläst sammansättning. Mer information finns i Blazor WebAssembly lazy loading assemblies not working when using @ref attribute in the component (dotnet/aspnetcore #29342).

Ytterligare resurser