Skip to content

[blazor][wasm] Fix hot reload IL trimming#65903

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/optimize-il-trimming-blazor-wasm
Draft

[blazor][wasm] Fix hot reload IL trimming#65903
Copilot wants to merge 2 commits intomainfrom
copilot/optimize-il-trimming-blazor-wasm

Conversation

Copy link
Contributor

Copilot AI commented Mar 23, 2026

Fix hot reload IL trimming

Summary

This PR improves IL trimming effectiveness for Blazor WebAssembly apps by making the hot reload feature switch properly recognized by the IL trimmer. Previously, hot reload–related code (caches, event subscriptions, metadata update handlers) was not trimmed away in published WASM apps because the trimmer could not statically determine that MetadataUpdater.IsSupported was false.

Problem

HotReloadManager.MetadataUpdateSupported was backed by MetadataUpdater.IsSupported, which returns false at runtime in trimmed/published WASM builds. However, the IL trimmer could not prove this statically. As a result:

  • All hot reload cache-clearing event handlers were retained in trimmed output.
  • Static constructors across ~20 files registered hot reload callbacks that could never fire.
  • The HotReloadManager type itself and its dependency graph survived trimming.

Solution

  1. Introduced HotReloadManager.IsSupported — a static bool property annotated with [FeatureSwitchDefinition("System.Reflection.Metadata.MetadataUpdater.IsSupported")]. This tells the IL trimmer to substitute this property with false when the feature switch is disabled, enabling it to eliminate dead code behind the guard.

  2. Split the check into two levels:

    • HotReloadManager.IsSupported (static, trimmer-visible) — controls whether any hot reload infrastructure is linked.
    • HotReloadManager.IsEnabled (instance, runtime-mutable) — replaces the old MetadataUpdateSupported property, used for testing scenarios where hot reload behavior needs to be toggled at runtime.
  3. Updated all ~20 call sites from:

    if (HotReloadManager.Default.MetadataUpdateSupported)

    to:

    if (HotReloadManager.IsSupported && HotReloadManager.Default.IsEnabled)

    The static IsSupported check comes first so the trimmer can eliminate the entire if block (including the IsEnabled access and the callback registration) when the feature is disabled.

  4. Updated Renderer to use the same two-level guard pattern, replacing direct references to the old static HotReloadManager.MetadataUpdateSupported.

  5. Updated ILLink substitutions in ILLink.Substitutions.xml to target the new get_IsSupported method.

Testing

  • Unit tests (RendererTest.cs): Updated to use the new IsEnabled property for controlling hot reload behavior in tests.
  • E2E test (WebAssemblyTrimmingTest.cs): Added a new test that verifies HotReloadManager type is trimmed away in published WASM builds. Uses reflection (Type.GetType) to confirm the type is absent in trimmed output.
  • Test component (HotReloadTrimmingCheck.razor): A Blazor component that checks at runtime whether HotReloadManager is present via reflection, reporting true/false.

Files changed

Core change

  • HotReloadManager.cs — Added [FeatureSwitchDefinition]-annotated IsSupported property; renamed MetadataUpdateSupported to IsEnabled.

Updated call sites (mechanical)

All files below changed from HotReloadManager.Default.MetadataUpdateSupported to HotReloadManager.IsSupported && HotReloadManager.Default.IsEnabled:

  • AttributeAuthorizeDataCache.cs
  • BindConverter.cs
  • ChangeDetection.cs
  • ComponentFactory.cs
  • DefaultComponentActivator.cs
  • DefaultComponentPropertyActivator.cs
  • PersistentServicesRegistry.cs
  • PersistentStateValueProviderKeyResolver.cs
  • PersistentValueProviderComponentSubscription.cs
  • ComponentProperties.cs
  • RenderHandle.cs
  • EventArgsTypeCache.cs
  • RenderTreeDiffBuilder.cs
  • Renderer.cs
  • RouteView.cs
  • RouteTable.cs
  • Router.cs
  • EndpointComponentState.cs
  • FieldIdentifier.cs
  • ExpressionFormatter.cs
  • RootTypeCache.cs
  • ExpressionMemberAccessor.cs
  • JSComponentInterop.cs

Trimmer configuration

  • ILLink.Substitutions.xml — Updated method signature from get_MetadataUpdateSupported to get_IsSupported.

Tests

  • RendererTest.cs — Updated to use IsEnabled instead of MetadataUpdateSupported.
  • WebAssemblyTrimmingTest.cs — New E2E test verifying HotReloadManager is trimmed in WASM publish.
  • HotReloadTrimmingCheck.razor — New test component for runtime type presence check.
  • Index.razor — Registered the new test component.
  • Components.TestServer.csproj — Set MetadataUpdaterSupport=true for trimmed test builds.
  • HotReloadStartup.cs — Updated to use IsEnabled.

@github-actions github-actions bot added the area-blazor Includes: Blazor, Razor Components label Mar 23, 2026
Copilot AI requested a review from pavelsavara March 23, 2026 06:39
@pavelsavara pavelsavara added this to the .NET 11 Planning milestone Mar 23, 2026
@pavelsavara pavelsavara changed the title Use [FeatureSwitchDefinition] for hot reload guards in Renderer to enable IL trimming [blazor][wasm] Fix IL hot reload trimming Mar 24, 2026
@pavelsavara pavelsavara changed the title [blazor][wasm] Fix IL hot reload trimming [blazor][wasm] Fix hot reload IL trimming Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants