Skip to content

Conversation

@ilonatommy
Copy link
Member

@ilonatommy ilonatommy commented Jan 13, 2026

dotnet new webworker adds a new project with WebWorker support to existing blazor applications

Background

Blazor WASM applications with heavy computing had to rely on the server requests. Computing on UI thread interfered with UI rendering and affected UX. In net10 we added an article with a sample application to make offloading the heavy work to WebWorker easier. In net11 we decided that we should add an official support for a template of c# library that would be added to existing WASM projects. It is this PR.

Usage

Typically, the template should be called in existing WASM application (e.g. in .Client project of Blazor Web app). It has two modes: --empty that adds only the WebWorker project with a README on how to use the API and default that additionally edits the existing WASM application by adding sample files. See: demo option.

# 1. Create Blazor WebAssembly or Blazor Web app (if not existing)
dotnet new blazorwasm -o MyApp

# 2. Make sure you're in the WASM app directory
cd MyApp

# 3. Apply the webworker template
dotnet new webworker

Demo option

The template item with --empty option adds a directory with a library project that contains a README file with API description and quick start tutorial.

image image

The template item without --empty option, additionally tries to update the existing blazor application:

  • add project reference to the webworker library project
  • add demo page in Pages directory (creates directory if does not exist)
  • add models/worker files
  • add AllowUnsafeBlocks=true property that requires user's consent (opens a dialog that can be skipped with --allow-scripts Yes)

Demo page fetches issues from a chosen repository with GitHub API. User can do it in WebWorker and in UI thread, while clicking the counter button and they can compare the statistics for time spent in fetch/JSON deserialization/data processing methods. Clicking affects UI thread results but cannot affect WebWorker results. Because GitHub API has its limitations without authentication, we provide an option to pass token to elevate the limits.

Demo uses following WebWorker APIs:

  • InitializeAsync() - loads the worker javascript file that initializes another .NET runtime
  • InvokeStringAsync() - invokes worker methods that return string. In our case the response is JSON that can be deserialized to GitHubMetrics
  • SetProgressCallback - to inform UI thread about the state of work in the WebWorker we can call JSImported method: globalThis.postProgress from WebWorker. UI thread has to have a callback set to the progress events.
webworker-demo-page image image

Fixes dotnet/runtime#95452

@ilonatommy ilonatommy added this to the 11.0-preview1 milestone Jan 13, 2026
@ilonatommy ilonatommy self-assigned this Jan 13, 2026
@ilonatommy ilonatommy added the area-blazor Includes: Blazor, Razor Components label Jan 13, 2026
The webworker item template generates a .csproj file into the content/
folder during build. NuGet was discovering and trying to restore this
generated project, but it failed because:

1. The package Microsoft.AspNetCore.Components.WebAssembly version
   11.0.0-ci doesn't exist in NuGet feeds (it's built in this repo)
2. The generated project was being evaluated before the package was built

Fix: Add Web.ItemTemplates/content/**/*.proj to ProjectToExclude in
eng/Build.props, matching the existing exclusion for Web.ProjectTemplates.

Also simplified Directory.Build.props in the content folder to remove
the sources.props import which is no longer needed since the projects
are excluded from build.
The ByteOrderMarkTest requires all .razor files in templates to have
UTF-8 BOM (Byte Order Mark) for proper encoding detection.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new dotnet new webworker template that enables WebWorker support for Blazor WebAssembly applications, allowing compute-intensive .NET code to run off the main UI thread for improved responsiveness. The template provides both an infrastructure-only mode (--empty) and a full mode with demo code showcasing GitHub API integration.

Changes:

  • New WebWorker item template with client library, JavaScript worker infrastructure, and optional demo files
  • Integration with BlazorWeb template to optionally include WorkerClient project
  • Comprehensive README documentation and localization for 13 languages

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/.template.config/template.json Template configuration defining parameters, symbols, and post-actions
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/WebWorkerTemplate.WorkerClient/WorkerClient.cs C# client for communicating with WebWorker via JSInterop
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/WebWorkerTemplate.WorkerClient/wwwroot/worker.js JavaScript WebWorker entry point for loading .NET runtime
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/WebWorkerTemplate.WorkerClient/wwwroot/worker-client.js JavaScript client for managing worker lifecycle and message passing
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/Worker/GitHubWorker.cs Demo worker class showing GitHub API data processing
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/Pages/WebWorkerDemo.razor.cs Demo Blazor page comparing WebWorker vs UI thread performance
src/ProjectTemplates/Web.ItemTemplates/content/WebWorker/Models/GitHubModels.cs Model classes for GitHub API responses
src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/.template.config/template.json Updated to reference WorkerClient project
src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1.sln Solution file with conditional WorkerClient project inclusion
src/ProjectTemplates/Web.ItemTemplates/Microsoft.DotNet.Web.ItemTemplates.csproj Build configuration for generating WorkerClient.csproj
eng/Build.props Updated to exclude template content projects from build
src/ProjectTemplates/Web.ItemTemplates/.gitignore Ignore generated .csproj files
Multiple localization files Translated template descriptions for 13 languages

Copy link
Member

@pavelsavara pavelsavara left a comment

Choose a reason for hiding this comment

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

Looks good overall, thanks!

/**
* Creates and initializes the WebWorker with event handlers.
*/
function createWorker() {
Copy link
Member

Choose a reason for hiding this comment

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

Someone may want to have multiple workers. Should we return worker ID ? And then require such id as first parameter to all client calls ?

probably, this is overkill and should keep it simple.

Copy link
Member Author

Choose a reason for hiding this comment

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

@javiercn?
I'm voting for simplicity, adding id is not a big change and my rule for this template was: add only bits that are used. I made an exception only for termination method because without it, the method set did not look complete.

@@ -0,0 +1,19 @@
{
"author": "Microsoft",
Copy link
Member Author

Choose a reason for hiding this comment

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

Question:
Is it okay to add AI-created translations? That's how I got them. If not, what's the process?

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.

[browser][doc] how to start dotnet on WebWorker + demo

2 participants