[Blazor] Replace DevServer with BlazorGateway for standalone WASM apps#65982
Open
[Blazor] Replace DevServer with BlazorGateway for standalone WASM apps#65982
Conversation
This was referenced Mar 26, 2026
Open
javiercn
commented
Mar 26, 2026
Member
Author
There was a problem hiding this comment.
This is temporary until an SDK with the functionality flows here
javiercn
commented
Mar 26, 2026
Member
Author
There was a problem hiding this comment.
Temporary until the SDK update flows to asp.net core
Contributor
There was a problem hiding this comment.
Pull request overview
This PR replaces the Blazor WebAssembly DevServer with a new Microsoft.AspNetCore.Components.Gateway host for serving standalone WASM apps in development/testing, and updates test/benchmark assets to use the new Gateway (including SPA fallback routing via static web assets endpoints).
Changes:
- Adds a new Gateway project (
Microsoft.AspNetCore.Components.Gateway) with aBlazorGateway.BuildWebHost(args)entrypoint anddotnet runintegration via MSBuild targets. - Updates Components test infrastructure (E2E + Components.TestServer) to start the Gateway instead of DevServer and passes static web assets manifests explicitly.
- Introduces a temporary
SpaFallback.targetsimported by multiple WASM test apps to add a{**path:nonfile}SPA fallback endpoint.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/WebAssembly/testassets/SpaFallback.targets | New MSBuild targets to inject SPA fallback static web asset endpoint. |
| src/Components/test/testassets/GlobalizationWasmApp/GlobalizationWasmApp.csproj | Imports SPA fallback targets for this test asset. |
| src/Components/test/testassets/Components.TestServer/Program.cs | Switches dev-host scenario to use BlazorGateway and passes manifests via args. |
| src/Components/test/testassets/Components.TestServer/Components.TestServer.csproj | Uses shared-source BlazorGateway.cs, adds YARP refs, and removes transitive framework ref. |
| src/Components/test/testassets/BasicTestApp/BasicTestApp.csproj | Imports SPA fallback targets. |
| src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj | Normalizes project file header/encoding. |
| src/Components/test/E2ETest/Infrastructure/ServerFixtures/BlazorWasmTestAppFixture.cs | Uses BlazorGateway and passes static web assets manifests to host. |
| src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj | Imports SPA fallback targets for benchmark app. |
| src/Components/WebAssembly/testassets/ThreadingApp/ThreadingApp.csproj | Imports SPA fallback targets. |
| src/Components/WebAssembly/testassets/StandaloneApp/StandaloneApp.csproj | Imports Gateway run targets and SPA fallback; sets Gateway DLL location override. |
| src/Components/WebAssembly/testassets/SpaFallback.targets | New MSBuild targets to inject SPA fallback static web asset endpoint (Components copy). |
| src/Components/Gateway/src/build/Microsoft.AspNetCore.Components.Gateway.targets | Overrides dotnet run args for WASM projects to launch Gateway with manifest paths. |
| src/Components/Gateway/src/blazor-gateway.runtimeconfig.json.in | Adds runtimeconfig template for the packaged Gateway tool. |
| src/Components/Gateway/src/Program.cs | Gateway entrypoint calling BlazorGateway.BuildWebHost(args).Run(). |
| src/Components/Gateway/src/Microsoft.AspNetCore.Components.Gateway.nuspec | Packages Gateway tool + build targets into the shipping NuGet package. |
| src/Components/Gateway/src/Microsoft.AspNetCore.Components.Gateway.csproj | New shipping project (Web SDK) with YARP/service-discovery references and pack settings. |
| src/Components/Gateway/src/BlazorGateway.cs | Implements Gateway host setup: static web assets, optional YARP proxy, app config endpoints, and static assets mapping per client app. |
| eng/Versions.props | Adds version properties for YARP + service discovery packages. |
| eng/Dependencies.props | Adds YARP + service discovery packages to dependency tracking. |
src/Components/WebAssembly/testassets/StandaloneApp/StandaloneApp.csproj
Outdated
Show resolved
Hide resolved
src/Components/test/testassets/GlobalizationWasmApp/GlobalizationWasmApp.csproj
Outdated
Show resolved
Hide resolved
3576550 to
11863e3
Compare
3 tasks
- Single Program.cs with top-level statements, pure config-driven
- Supports standalone (MSBuild targets) and Aspire (env vars/YARP)
- Gateway targets: _WebAssemblyUserRunParameters to skip WasmAppHost,
AfterTargets ComputeRunArguments with ResolveStaticWebAssetsConfiguration
to resolve manifest paths via Path.Combine(MSBuildProjectDirectory)
- Temporary SpaFallback.targets in testassets: pure MSBuild target that
clones identity index.html endpoint as {**path:nonfile} catch-all
(replaces inline C# task, will be removed when SDK ships
StaticWebAssetSpaFallbackEnabled)
- Update StandaloneApp.csproj to import Gateway + SpaFallback targets
- Extract BlazorGateway.BuildWebHost() into BlazorGateway.cs (shared source) - Update Components.TestServer and BlazorWasmTestAppFixture to use BlazorGateway - Add YARP packages (Yarp.ReverseProxy, ServiceDiscovery) via repo's <Reference> pattern - Add SpaFallback.targets to BasicTestApp, ThreadingApp, and Wasm.Performance.TestApp - Remove Program.BuildWebHost.cs Compile Include from E2ETests (gets it via TestServer ref)
Pass explicit --staticWebAssets, --ClientApps:app:EndpointsManifest, and --ClientApps:app:PathPrefix arguments from call sites instead of deriving manifest paths inside BlazorGateway. Add SpaFallback.targets to GlobalizationWasmApp.
SpaFallback.targets added a {**path:nonfile} catch-all to BasicTestApp's endpoint manifest, which propagated to Components.TestServer. MapStaticAssets hardcodes Order=-100 on all endpoints, giving the catch-all higher priority than Razor component routes (Order=0), causing all non-file URLs to serve index.html instead of server-rendered pages.
- Remove SpaFallback.targets import from BasicTestApp.csproj
- Replace the .Add() Order-override in BlazorGateway with MapFallbackToFile, matching the old DevServer approach
11863e3 to
faab532
Compare
javiercn
commented
Mar 29, 2026
Comment on lines
+59
to
+62
| // SPA fallback: serve index.html for any non-file URL path, similar to | ||
| // the old DevServer's MapFallbackToFile("index.html"). This is registered | ||
| // after MapStaticAssets so that specific static file routes take precedence. | ||
| app.MapFallbackToFile("index.html"); |
Member
Author
There was a problem hiding this comment.
This is until we get fallbacks on the SDK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces
Microsoft.AspNetCore.Components.Gateway— a lightweight ASP.NET Core host that replaces the DevServer for serving standalone Blazor WebAssembly applications during development and production.Changes
New: Gateway project (
src/Components/Gateway/src/)BlazorGateway.cs— StaticBuildWebHost(string[] args)method configurable in two modes:--applicationpathCLI arg (used bydotnet runand E2E tests)ClientAppsconfig section for multiple client apps, YARP reverse proxy, config endpointsProgram.cs— Entry point that callsBlazorGateway.BuildWebHost(args).Run()build/Microsoft.AspNetCore.Components.Gateway.targets) — Imported by WASM projects to overridedotnet runbehavior: sets_WebAssemblyUserRunParameters=true, resolves manifest paths viaComputeRunArguments{**path:nonfile}catch-all endpoint to the static web assets endpoints manifest (clones identityindex.htmlendpoint)Updated: E2E test infrastructure
BlazorWasmTestAppFixturenow callsBlazorGateway.BuildWebHost()instead of DevServerComponents.TestServerincludesBlazorGateway.csas shared source and uses it for the "Dev server client-side blazor" scenario<Reference>pattern (eng/Versions.props+eng/Dependencies.props)SpaFallback.targetsimported into BasicTestApp, ThreadingApp, and Wasm.Performance.TestAppKey design decisions
<Compile Include>—BlazorGateway.csis included in test projects as source rather than referenced as a project, avoiding assembly conflicts with the test host'sProgramclass_RemoveTransitiveAspNetCoreFrameworkReferencetarget — In TestServer, removes YARP's transitiveFrameworkReferencetoMicrosoft.AspNetCore.AppafterAddTransitiveFrameworkReferencesbut beforeResolveTargetingPackAssetsTesting
E2E test validation in progress across 5 waves:
StandaloneAppTest.HasTitle,HasHeading,BasicTestAppCanBeServed✅