-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Background and Motivation
Work continues in the runtime repo on WebAssembly multithreading. It's now pretty easy to enable and use - people just need to:
A. Add <WasmEnableThreads>true</WasmEnableThreads> in the wasm project csproj
B. Ensure the site is served with the relevant Cross-Origin-... headers as per browser requirements
- For Blazor WebAssembly Standalone, during development the dev server will automatically serve these headers based on
WasmEnableThreads(because there's no easy way to configure the dev server, so we have to do it automatically). And in production, the developer has to configure the server's response headers themselves because Blazor/ASP.NETCore is not involved. This PR does not affect it. - For traditional Blazor WebAssembly hosted-on-ASP.NET-Core (i.e., using
MapBlazorFrameworkFilesandMapFallbackToFile, not the new .NET 8 Blazor Web model), developers can easily write a few lines of ASP.NET Core middleware to serve the necessary headers, which we can document. This PR does not affect it. - For Blazor Web using the
InteractiveWebAssemblyrender mode, this PR adds a simple API for serving the headers on the correct endpoints matching what gets registered byMapRazorComponents. That is, it serves them for any Razor Components endpoint (since it may be or contain anInteractiveWebAssemblycomponent), plus for_framework/*(since that's required to load the Blazor WebAssembly runtime with SharedArrayBuffer support in the worker thread).
Proposed API
namespace Microsoft.AspNetCore.Components.WebAssembly.Server;
public sealed class WebAssemblyComponentsEndpointOptions
{
+ /// <summary>
+ /// Gets or sets a flag to determine whether to enable WebAssembly multithreading. If true,
+ /// the server will add headers similar to <code>Cross-Origin-Embedder-Policy: require-corp</code> and
+ /// <code>Cross-Origin-Opener-Policy: same-origin</code> on the response for the host page, because
+ /// this is required to enable the SharedArrayBuffer feature in the browser.
+ ///
+ /// Note that enabling this feature can restrict your ability to use other JavaScript APIs. For more
+ /// information, see <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements" />.
+ /// </summary>
+ public bool ServeMultithreadingHeaders { get; set; }
}Usage Examples
app.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode(options => { options.ServeMultithreadingHeaders = true; })
.AddAdditionalAssemblies(typeof(MyWebAssemblyApp.Pages.Index).Assembly);Alternative Designs
Overall, since this feature is nascent and remains experimental, I'm erring on the side of making it more explicit and literal so people who turn it on know what they are getting into. In the future if we get to the point that wasm multithreading is so good that most people should enable it, we retain the option to streamline the usage.
Alternative: Infer it automatically
We could try to infer this based on <WasmEnableThreads> in the wasm csproj, but:
- There could be multiple wasm apps. What if they want different configurations?
- Since this is an early and quite experimental feature, it's really good to force developers to opt in to serving the COOP headers explicitly. Doing so can restrict the availability of other JS APIs (e.g., can interfere with popups that might be used for auth flows) as described at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements. It might turn out to be fine, but in case this causes issues for people, it's really good that the developer has a chance to discover what they are enabling and the possible side-effects of that.
Alternative: Extension method
An alternative API would be making it an extension method on RazorComponentsEndpointConventionBuilder, e.g.:
app.MapRazorComponents<App>().AddInteractiveWebAssemblyRenderMode().ServeWasmMultithreadingHeaders();
... but that would be very strange and ambiguous since you could also write:
app.MapRazorComponents<App>().AddInteractiveServerRenderMode().ServeWasmMultithreadingHeaders();
I prefer it being an option on AddInteractiveWebAssemblyRenderMode since it is more specific and accurate, as it only applies within that case.
Alternative: Naming
It would be more obvious to call it EnableMultithreading instead of ServeMultithreadingHeaders, but that would not so well serve the purpose of helping developer understand what exactly they are enabling and how it might have other side effects.
Risks
Nothing obvious.