Compartilhar via


Assemblies de carregamento lento no Blazor WebAssembly do ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para a versão atual, consulte a versão .NET 9 deste artigo.

O desempenho de inicialização do aplicativo Blazor WebAssembly pode ser aprimorado ao adiar o carregamento de assemblies do aplicativo criados pelo desenvolvedor até que eles sejam necessários, o que é chamado de lazy loading.

As seções iniciais deste artigo abrangem a configuração do aplicativo. Para obter uma demonstração de trabalho, consulte a seção Exemplo completo no final deste artigo.

Este artigo é válido somente para aplicativos Blazor WebAssembly. O carregamento lento do assembly não beneficia aplicativos do lado do servidor porque os aplicativos renderizados pelo servidor não baixam assemblies para o cliente.

O carregamento lento não deve ser usado para assemblies de runtime principais, que podem ser cortados no momento da publicação e ficar indisponíveis no cliente quando o aplicativo é carregado.

Espaço reservado para extensão de nome de arquivo ({FILE EXTENSION}) para arquivos do assembly

Os arquivos do assembly usam o formato de empacotamento Webcil para assemblies do .NET com uma extensão de nome de arquivo .wasm.

Ao longo do artigo, o marcador {FILE EXTENSION} representa "wasm".

Os arquivos do assembly são baseados em Bibliotecas de Link Dinâmico (DLLs) com uma extensão de nome de arquivo .dll.

Ao longo do artigo, o marcador {FILE EXTENSION} representa "dll".

Configuração do arquivo de projeto

Marque assemblies para carregamento lento no arquivo de projeto do aplicativo (.csproj) usando o item BlazorWebAssemblyLazyLoad. Use o nome do assembly com a extensão de nome de arquivo. A estrutura Blazor impede que o assembly seja carregado na inicialização do aplicativo.

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

O marcador de posição {ASSEMBLY NAME} é o nome do assembly, e o marcador de posição {FILE EXTENSION} é a extensão do arquivo. A extensão de arquivo é obrigatória.

Inclua um item BlazorWebAssemblyLazyLoad para cada montagem. Se um assembly tiver dependências, inclua uma entrada BlazorWebAssemblyLazyLoad para cada dependência.

Configuração do componenteRouter

A estrutura Blazor registra automaticamente um serviço singleton para assemblies de carregamento lento em aplicativos Blazor WebAssembly do lado do cliente, LazyAssemblyLoader. O método LazyAssemblyLoader.LoadAssembliesAsync:

  • Usa JS interop para buscar assemblies por meio de uma chamada de rede.
  • Carrega assemblies (componentes) no ambiente de execução que opera com o WebAssembly no navegador.

Observação

As diretrizes para soluçõesBlazor WebAssemblyhospedadas estão abrangidas na seção Assemblies de carregamento lento em uma soluçãoBlazor WebAssembly hospedada.

O componente do Blazor's Router designa os assemblies que Blazor procura por componentes rotuláveis e também é responsável pela renderização do componente para a rota em que o usuário navega. O Router método OnNavigateAsync do componente é usado em conjunto com o carregamento lento para carregar os assemblies corretos para os pontos de extremidade que um usuário solicita.

A lógica é implementada no interior de OnNavigateAsync para determinar os assemblies a serem carregados com LazyAssemblyLoader. As opções de como estruturar a lógica incluem:

  • Verificações condicionais no método OnNavigateAsync.
  • Uma tabela de pesquisa que mapeia rotas para nomes de assembly, injetadas no componente ou implementadas no código do componente.

No exemplo a seguir:

  • O namespace para Microsoft.AspNetCore.Components.WebAssembly.Services é especificado.
  • O serviço LazyAssemblyLoader é injetado (AssemblyLoader).
  • O espaço reservado {PATH} é o caminho onde a lista de assemblies deve ser carregada. O exemplo usa uma verificação condicional para um único caminho que carrega um único conjunto de assemblies.
  • O espaço reservado {LIST OF ASSEMBLIES} é a lista separada por vírgulas de cadeias de caracteres de nome de arquivo de assembly, incluindo suas extensões de arquivo (por exemplo, "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);
           }
    }
}

Observação

O exemplo anterior não mostra o conteúdo da marcação Router do componente Razor (...). Para obter uma demonstração com código completo, consulte a seção Exemplo completo deste artigo.

Observação

Com a versão do .NET 5.0.1 e para quaisquer versões adicionais de 5.x, o Router componente inclui o PreferExactMatches parâmetro definido como @true. Para obter mais informações, consulte Migrar do ASP.NET Core 3.1 para o .NET 5.

Montagens que incluem componentes roteáveis

Quando a lista de assemblies inclui componentes roteáveis, a lista de assemblies de um determinado caminho é passada para a coleção Router do componente AdditionalAssemblies.

No exemplo a seguir:

  • A lista<Assembly> em lazyLoadedAssemblies passa a lista de assemblies para AdditionalAssemblies. A estrutura pesquisa os assemblies em busca de rotas e atualiza a coleção de rotas se novas rotas forem encontradas. Para acessar o tipo Assembly, o namespace para System.Reflection é incluído na parte superior do arquivo App.razor.
  • O espaço reservado {PATH} é o caminho onde a lista de assemblies deve ser carregada. O exemplo usa uma verificação condicional para um único caminho que carrega um único conjunto de assemblies.
  • O espaço reservado {LIST OF ASSEMBLIES} é a lista separada por vírgulas de cadeias de caracteres de nome de arquivo de assembly, incluindo suas extensões de arquivo (por exemplo, "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);
           }
    }
}

Observação

O exemplo anterior não mostra o conteúdo da marcação Router do componente Razor (...). Para obter uma demonstração com código completo, consulte a seção Exemplo completo deste artigo.

Observação

Com a versão do .NET 5.0.1 e para quaisquer versões adicionais de 5.x, o Router componente inclui o PreferExactMatches parâmetro definido como @true. Para obter mais informações, consulte Migrar do ASP.NET Core 3.1 para o .NET 5.

Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

Interação do usuário com conteúdo <Navigating>

Ao carregar as assemblies, o que pode levar vários segundos, o componente Router pode mostrar ao usuário que está ocorrendo uma transição de página com a propriedade Navigating do roteador.

Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

Gerenciar cancelamentos em OnNavigateAsync

O objeto NavigationContext passado ao callback OnNavigateAsync contém um CancellationToken que é definido quando ocorre um novo evento de navegação. O retorno de chamada OnNavigateAsync precisa lançar quando esse token de cancelamento é definido a fim de evitar continuar a executar o retorno de chamada OnNavigateAsync em uma navegação desatualizada.

Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

OnNavigateAsync arquivos de eventos e de assemblies renomeados

O carregador de recursos depende dos nomes de assembly definidos no arquivo de manifesto de inicialização. Se os assemblies forem renomeados, os nomes de assembly usados em um OnNavigateAsync retorno de chamada e os nomes de assembly no arquivo de manifesto de inicialização estarão fora de sincronia.

Para corrigir isso:

  • Verifique se o aplicativo está em execução no ambiente Production ao determinar quais nomes de assembly devem ser usados.
  • Armazene os nomes de assembly renomeados em um arquivo separado e, em seguida, consulte-o para determinar qual nome de assembly deve ser utilizado com o serviço LazyAssemblyLoader e o callback OnNavigateAsync.

Assemblies de carregamento lentos em uma solução Blazor WebAssembly hospedada

A implementação de carregamento lento da estrutura dá suporte ao carregamento lento com pré-geração em uma Blazor WebAssemblysolução hospedada. Durante a pré-geração, todos os assemblies, incluindo aqueles marcados para carregamento lento, são considerados carregados. Registre manualmente o serviço LazyAssemblyLoader no projeto Server.

Na parte superior do arquivo Program.cs do projeto Server, adicione o namespace para Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

No Program.cs do projeto Server, registre o serviço:

builder.Services.AddScoped<LazyAssemblyLoader>();

Na parte superior do arquivo Startup.cs do projeto Server, adicione o namespace para Microsoft.AspNetCore.Components.WebAssembly.Services:

using Microsoft.AspNetCore.Components.WebAssembly.Services;

No Startup.ConfigureServices (Startup.cs) do projeto Server, registre o serviço:

services.AddScoped<LazyAssemblyLoader>();

Exemplo completo

A demonstração nesta seção:

  • Cria um assembly de controles de robô (GrantImaharaRobotControls.{FILE EXTENSION}) como um componente de Razor biblioteca de classes (RCL) que inclui um componente Robot (Robot.razor com um modelo de rota de /robot).
  • Carrega o assembly da RCL de modo preguiçoso para renderizar seu componente Robot quando a URL /robot é solicitada pelo usuário.

Crie um aplicativo autônomo Blazor WebAssembly para demonstrar o carregamento lento do assembly de uma biblioteca de classes Razor. Dê ao projeto o nome de LazyLoadTest.

Adicione um projeto de biblioteca de classes do ASP.NET Core à solução:

  • Visual Studio: clique com o botão direito do mouse no arquivo de solução no Gerenciador de Soluções e selecione Adicionar>Novo projeto. Na caixa de diálogo de novos tipos de projeto, selecione Biblioteca de Classes Razor. Dê ao projeto o nome de GrantImaharaRobotControls. Não marque a caixa de seleção Páginas de suporte e exibições.
  • CLI do Visual Studio Code/.NET: execute dotnet new razorclasslib -o GrantImaharaRobotControls de um prompt de comando. A opção -o|--output cria uma pasta e nomeia o projeto GrantImaharaRobotControls.

Crie uma classe HandGesture na RCL com um método ThumbUp que hipoteticamente faz com que um robô execute um gesto de polegar para cima. O método aceita um argumento para o eixo, Left ou Right, como um enum. O método retorna true com êxito.

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

Adicione o componente a seguir à raiz do projeto da RCL. O componente permite que o usuário envie uma solicitação de gesto de polegar para cima à esquerda ou direita.

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

No projeto LazyLoadTest, crie uma referência de projeto para a RCL GrantImaharaRobotControls:

  • Visual Studio: clique com o botão direito do mouse no projeto LazyLoadTest e selecione Adicionar>Referência do projeto para adicionar uma referência de projeto para a RCL GrantImaharaRobotControls.
  • CLI do Visual Studio Code/.NET: execute dotnet add reference {PATH} em um shell de comando da pasta do projeto. O espaço reservado {PATH} é o caminho para o projeto da RCL.

Especifique o assembly da RCL para carregamento lento no arquivo de projeto do aplicativo LazyLoadTest (.csproj):

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

O componente Router a seguir demonstra o carregamento do assembly GrantImaharaRobotControls.{FILE EXTENSION} quando o usuário navega para /robot. Substitua o componente padrão App do aplicativo pelo componente a seguir App.

Durante as transições de página, uma mensagem com estilo é exibida para o usuário com o elemento <Navigating>. Para obter mais informações, consulte a seção Interação do usuário com conteúdo <Navigating>.

O assembly é atribuído a AdditionalAssemblies, o que resulta no roteador pesquisando componentes roteáveis no assembly, onde ele encontra o componente Robot. A rota do componente Robot é adicionada à coleção de rotas do aplicativo. Para obter mais informações, consulte o artigo Roteamento e navegação Blazor do ASP.NET Core e a seção Assemblies que incluem componentes roteáveis deste artigo.

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

Compile e execute o aplicativo.

Quando o componente Robot da RCL é solicitado em /robot, o assembly GrantImaharaRobotControls.{FILE EXTENSION} é carregado e o componente Robot é renderizado. Você pode inspecionar o carregamento do assembly na guia Rede das ferramentas de desenvolvedor do navegador.

Solucionar problemas

  • Se ocorrer uma renderização inesperada, como renderizar um componente de uma navegação anterior, confirme se o código será gerado se o token de cancelamento estiver definido.
  • Se os assemblies configurados para carregamento lento forem carregados inesperadamente no início do aplicativo, verifique se o assembly está marcado para carregamento lento no arquivo de projeto.

Observação

Existe um problema conhecido para carregar tipos de assembly carregado lentamente. Para obter mais informações, consulte Blazor WebAssembly lazy loading assemblies not working when using @ref attribute in the component (dotnet/aspnetcore #29342).

Recursos adicionais