diff --git a/src/Components/WebAssembly/Build/src/Tasks/GenerateBlazorBootJson.cs b/src/Components/WebAssembly/Build/src/Tasks/GenerateBlazorBootJson.cs
index 047f08d5dd..d3f1de66a9 100644
--- a/src/Components/WebAssembly/Build/src/Tasks/GenerateBlazorBootJson.cs
+++ b/src/Components/WebAssembly/Build/src/Tasks/GenerateBlazorBootJson.cs
@@ -88,6 +88,9 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build
case "assembly":
resourceList = resourceData.assembly;
break;
+ case "dynamicAssembly":
+ resourceList = resourceData.dynamicAssembly;
+ break;
case "pdb":
resourceData.pdb ??= new ResourceHashesByNameDictionary();
resourceList = resourceData.pdb;
@@ -207,6 +210,11 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build
///
public ResourceHashesByNameDictionary assembly { get; set; } = new ResourceHashesByNameDictionary();
+ ///
+ /// Assembly (.dll) resources that are loaded dynamically during runtime
+ ///
+ public ResourceHashesByNameDictionary dynamicAssembly { get; set; } = new ResourceHashesByNameDictionary();
+
///
/// "debug" (.pdb) resources
///
@@ -221,4 +229,4 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build
}
#pragma warning restore IDE1006 // Naming Styles
}
-}
+}
\ No newline at end of file
diff --git a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
index 7d6eb810b4..c143445685 100644
--- a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
+++ b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets
@@ -129,6 +129,7 @@
<_BlazorOutputWithTargetPath Include="@(_BlazorResolvedAssembly)">
assembly
pdb
+ dynamicAssembly
%(FileName)%(Extension)
$(_BlazorRuntimeBinOutputPath)%(FileName)%(Extension)
diff --git a/src/Components/WebAssembly/Build/test/BuildIntegrationTests/BuildLazyLoadTest.cs b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/BuildLazyLoadTest.cs
new file mode 100644
index 0000000000..dc6be8d80e
--- /dev/null
+++ b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/BuildLazyLoadTest.cs
@@ -0,0 +1,176 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Testing;
+using Xunit;
+using static Microsoft.AspNetCore.Components.WebAssembly.Build.WebAssemblyRuntimePackage;
+
+namespace Microsoft.AspNetCore.Components.WebAssembly.Build
+{
+ public class BuildLazyLoadTest
+ {
+ [Fact]
+ public async Task Build_LazyLoadExplicitAssembly_Debug_Works()
+ {
+ // Arrange
+ using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
+ project.Configuration = "Debug";
+
+ project.AddProjectFileContent(
+@"
+
+
+
+");
+
+ var result = await MSBuildProcessManager.DotnetMSBuild(project);
+
+ var buildOutputDirectory = project.BuildOutputDirectory;
+
+ // Verify that a blazor.boot.json file has been created
+ Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
+ // And that the assembly is in the output
+ Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
+
+ var bootJson = ReadBootJsonData(result, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"));
+
+ // And that it has been labelled as a dynamic assembly in the boot.json
+ var dynamicAssemblies = bootJson.resources.dynamicAssembly;
+ var assemblies = bootJson.resources.assembly;
+
+ Assert.NotNull(dynamicAssemblies);
+ Assert.Contains("RazorClassLibrary.dll", dynamicAssemblies.Keys);
+ Assert.DoesNotContain("RazorClassLibrary.dll", assemblies.Keys);
+
+ // App assembly should not be lazy loaded
+ Assert.DoesNotContain("standalone.dll", dynamicAssemblies.Keys);
+ Assert.Contains("standalone.dll", assemblies.Keys);
+ }
+
+ [Fact]
+ public async Task Build_LazyLoadExplicitAssembly_Release_Works()
+ {
+ // Arrange
+ using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
+ project.Configuration = "Release";
+
+ project.AddProjectFileContent(
+@"
+
+
+
+");
+
+ var result = await MSBuildProcessManager.DotnetMSBuild(project);
+
+ var buildOutputDirectory = project.BuildOutputDirectory;
+
+ // Verify that a blazor.boot.json file has been created
+ Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
+ // And that the assembly is in the output
+ Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
+
+ var bootJson = ReadBootJsonData(result, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"));
+
+ // And that it has been labelled as a dynamic assembly in the boot.json
+ var dynamicAssemblies = bootJson.resources.dynamicAssembly;
+ var assemblies = bootJson.resources.assembly;
+
+ Assert.NotNull(dynamicAssemblies);
+ Assert.Contains("RazorClassLibrary.dll", dynamicAssemblies.Keys);
+ Assert.DoesNotContain("RazorClassLibrary.dll", assemblies.Keys);
+
+ // App assembly should not be lazy loaded
+ Assert.DoesNotContain("standalone.dll", dynamicAssemblies.Keys);
+ Assert.Contains("standalone.dll", assemblies.Keys);
+ }
+
+ [Fact]
+ public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
+ {
+ // Arrange
+ using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
+ project.Configuration = "Debug";
+
+ project.AddProjectFileContent(
+@"
+
+
+
+");
+
+ var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
+
+ var publishDirectory = project.PublishOutputDirectory;
+
+ // Verify that a blazor.boot.json file has been created
+ Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "blazor.boot.json");
+ // And that the assembly is in the output
+ Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
+
+ var bootJson = ReadBootJsonData(result, Path.Combine(publishDirectory, "wwwroot", "_framework", "blazor.boot.json"));
+
+ // And that it has been labelled as a dynamic assembly in the boot.json
+ var dynamicAssemblies = bootJson.resources.dynamicAssembly;
+ var assemblies = bootJson.resources.assembly;
+
+ Assert.NotNull(dynamicAssemblies);
+ Assert.Contains("RazorClassLibrary.dll", dynamicAssemblies.Keys);
+ Assert.DoesNotContain("RazorClassLibrary.dll", assemblies.Keys);
+
+ // App assembly should not be lazy loaded
+ Assert.DoesNotContain("standalone.dll", dynamicAssemblies.Keys);
+ Assert.Contains("standalone.dll", assemblies.Keys);
+ }
+
+ [Fact]
+ public async Task Publish_LazyLoadExplicitAssembly_Release_Works()
+ {
+ // Arrange
+ using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
+ project.Configuration = "Release";
+
+ project.AddProjectFileContent(
+@"
+
+
+
+");
+
+ var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
+
+ var publishDirectory = project.PublishOutputDirectory;
+
+ // Verify that a blazor.boot.json file has been created
+ Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "blazor.boot.json");
+ // And that the assembly is in the output
+ Assert.FileExists(result, publishDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
+
+ var bootJson = ReadBootJsonData(result, Path.Combine(publishDirectory, "wwwroot", "_framework", "blazor.boot.json"));
+
+ // And that it has been labelled as a dynamic assembly in the boot.json
+ var dynamicAssemblies = bootJson.resources.dynamicAssembly;
+ var assemblies = bootJson.resources.assembly;
+
+ Assert.NotNull(dynamicAssemblies);
+ Assert.Contains("RazorClassLibrary.dll", dynamicAssemblies.Keys);
+ Assert.DoesNotContain("RazorClassLibrary.dll", assemblies.Keys);
+
+ // App assembly should not be lazy loaded
+ Assert.DoesNotContain("standalone.dll", dynamicAssemblies.Keys);
+ Assert.Contains("standalone.dll", assemblies.Keys);
+ }
+
+ private static GenerateBlazorBootJson.BootJsonData ReadBootJsonData(MSBuildResult result, string path)
+ {
+ return JsonSerializer.Deserialize(
+ File.ReadAllText(Path.Combine(result.Project.DirectoryPath, path)),
+ new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
+ }
+ }
+}