Skip to content

[wasm] Embed HotReload in WebAssembly SDK#52710

Closed
maraf wants to merge 19 commits intomainfrom
maraf/WasmHotReloadEmbed
Closed

[wasm] Embed HotReload in WebAssembly SDK#52710
maraf wants to merge 19 commits intomainfrom
maraf/WasmHotReloadEmbed

Conversation

@maraf
Copy link
Member

@maraf maraf commented Jan 28, 2026

Replace a PackageReference with content shipped inside of the SDK.
It requires to manually reference the dll and define a StaticWebAsset for JSInitializer.

The HotReload project for WebAssembly is pinned to net10.0 as we don't need to multi-target yet.
Baselines tests have a new token ${WebAssemblySdkPath} pointing to WebAssembly SDK inside .NET SDK

Fixes #49877
Fixes #52686
Fixes dotnet/aspnetcore#65261

@maraf maraf self-assigned this Jan 28, 2026
@maraf maraf changed the title Embed HotReload in WebAssembly SDK [wasm] Embed HotReload in WebAssembly SDK Jan 29, 2026
<Target Name="_ImplicitlyReferenceHotReload" BeforeTargets="ResolveProjectStaticWebAssets" AfterTargets="ResolveStaticWebAssetsConfiguration" Condition="'$(_WasmEnableHotReload)' == 'true'">
<PropertyGroup>
<_WasmHotReloadRoot>$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), '..', 'hotreload'))</_WasmHotReloadRoot>
<_WasmHotReloadDllPath Condition="$([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '10.0'))">net10.0</_WasmHotReloadDllPath>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tmat Do you prefer to multi-target the dll or pin it to .NET 10?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's pin to .NET 10 until we need runtime features that need higher version. It's simpler and reduces SDK size.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, let's target release/10.0.3xx branch instead of main.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather land it on main and backport it to 10. We are testing some scenarios only on main in runtime and I have some unpleasant memories when changes arrived there later due to delayed forward flow in SDK

@@ -35,18 +35,22 @@
</PropertyGroup>

<PropertyGroup>
<TargetFrameworks>$(SdkTargetFramework);net472</TargetFrameworks>
<!-- We are not using the assembly anywhere -->
<TargetFrameworks>$(SdkTargetFramework)</TargetFrameworks>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be TargetFramework (singular)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. For some reason it doesn't produce a correct layout - the output SDK folder contains just the dll

<Pack>true</Pack>
<PackagePath>targets</PackagePath>
</AdditionalContent>
<ProjectReference Include="..\..\BuiltInTools\HotReloadAgent.WebAssembly.Browser\Microsoft.DotNet.HotReload.WebAssembly.Browser.csproj">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think setting metadata of the ProjectReference like so and removing the <AdditionalContent> below would work

      <OutputItemType>AdditionalContent</OutputItemType>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>           
      <Pack>true</Pack>
      <PackagePath>hotreload</PackagePath>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It add items to the AdditionalContent, but the PackagePath metadata is ignored
image

@maraf
Copy link
Member Author

maraf commented Jan 30, 2026

Relevant test failure log

/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018: The "FilterStaticWebAssetEndpoints" task failed unexpectedly. [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018: System.ArgumentException: An item with the same key has already been added. Key: /datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.WebAssembly/hotreload/net10.0/wwwroot/Microsoft.DotNet.HotReload.WebAssembly.Browser.lib.module.js [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018:    at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018:    at Microsoft.AspNetCore.StaticWebAssets.Tasks.StaticWebAsset.ToAssetDictionary(ITaskItem[] candidateAssets, Boolean validate) in /_/src/StaticWebAssetsSdk/Tasks/Data/StaticWebAsset.cs:line 1237 [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018:    at Microsoft.AspNetCore.StaticWebAssets.Tasks.FilterStaticWebAssetEndpoints.Execute() in /_/src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetEndpoints.cs:line 35 [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Execute() [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
/datadisks/disk1/work/C4900A2F/p/d/sdk/11.0.100-ci/Sdks/Microsoft.NET.Sdk.StaticWebAssets/targets/Microsoft.NET.Sdk.StaticWebAssets.JSModules.targets(215,3): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(TaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask) [/datadisks/disk1/work/C4900A2F/t/dotnetSdkTests.qFYAxAdO/Publish_Hosti---AC2D7A92/BlazorMultipleApps.Server/BlazorMultipleApps.Server.csproj]
StdErr:

@maraf
Copy link
Member Author

maraf commented Jan 30, 2026

@javiercn How to handle when there two endpoints pointing to a single source file?

image

two-endpoints-pointing-to-the-same-source-file.zip

@javiercn
Copy link
Member

javiercn commented Feb 2, 2026

@maraf

@javiercn How to handle when there two endpoints pointing to a single source file?

image [two-endpoints-pointing-to-the-same-source-file.zip](https://github.com/user-attachments/files/24975041/two-endpoints-pointing-to-the-same-source-file.zip)

I would start tracing back where the endpoint is originated. Does it come from a referenced project? (Seems to be a FirstApp and SecondApp). Is there a potential bug on FilterStaticWebAssetEndpoints? https://github.com/dotnet/sdk/blob/main/src/StaticWebAssetsSdk/Tasks/FilterStaticWebAssetEndpoints.cs#L35

I imagine that what's different here is that the assets on a package get deduplicated, while the assets you are injecting manually on each app aren't getting de-duplicated.

What's the exact scenario this targets, multiple apps being referenced by a host app? If so, it should technically be the host app providing the hot reload script, not the referenced apps (the asset should be marked as project so that it doesn't flow to the consuming apps).

@lewing
Copy link
Member

lewing commented Feb 5, 2026

current version is #52816

lewing added a commit to lewing/sdk that referenced this pull request Feb 6, 2026
…et10.0

Two issues introduced by review feedback commits:

1. OutputItemType=AdditionalContent on ProjectReference doesn't flow
   PackagePath metadata to the created items (confirmed by @maraf in
   PR dotnet#52710). Restored the explicit AdditionalContent glob from
    that was working in the green commit.

2. HotReload csproj TFM changed from net10.0 to
   but Sdk.targets hardcodes _WasmHotReloadTfm=net10.0. Per @tmat's
   guidance in PR dotnet#52710: pin to net10.0 until higher version needed.

The ProjectReference still has SkipGetTargetFrameworkProperties,
ReferenceOutputAssembly=false, and UndefineProperties for net472
compatibility as @tmat requested.
@lewing lewing closed this Feb 7, 2026
@maraf maraf deleted the maraf/WasmHotReloadEmbed branch February 10, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

4 participants