This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
Note
This isn't the latest version of this article. For the current release, see the.NET 10 version of this article.
Warning
This version of ASP.NET Core is no longer supported. For more information, see the.NET and .NET Core Support Policy. For the current release, see the.NET 9 version of this article.
This article explains how to host and deploy Blazor WebAssembly apps.
With theBlazor WebAssembly hosting model:
This article pertains to the deployment scenario where the Blazor app is placed on a static hosting web server or service, .NET isn't used to serve the Blazor app. This strategy is covered in theStandalone deployment section and other articles in this node for IIS, Azure services, Apache, Nginx, and GitHub Pages.
The following deployment strategies are supported:
Subdomain hosting doesn't require special configuration of the app. Youdon't need to configure the app base path (the<base> tag inwwwroot/index.html) to host the app at a subdomain.
IIS sub-application hostingdoes require you to set the app base path. For more information and cross-links to further guidance on IIS sub-application hosting, seeHost and deploy ASP.NET Core Blazor.
When building a Blazor app that runs on the client (.Client project of a Blazor Web App or standalone Blazor WebAssembly app) and targets mobile device browsers, especially Safari on iOS, decreasing the maximum memory for the app with the MSBuild propertyEmccMaximumHeapSize may be required. The default value is 2,147,483,648 bytes, which may be too large and result in the app crashing if the app attempts to allocate more memory with the browser failing to grant it. The following example sets the value to 268,435,456 bytes in theProgram file:
When building a Blazor WebAssembly app that targets mobile device browsers, especially Safari on iOS, decreasing the maximum memory for the app with the MSBuild propertyEmccMaximumHeapSize may be required. The default value is 2,147,483,648 bytes, which may be too large and result in the app crashing if the app attempts to allocate more memory with the browser failing to grant it. The following example sets the value to 268,435,456 bytes in theProgram file:
<EmccMaximumHeapSize>268435456</EmccMaximumHeapSize>For more information onMono/WebAssembly MSBuild properties and targets, seeWasmApp.Common.targets (dotnet/runtime GitHub repository).
Webcil is a web-friendly packaging format for .NET assemblies designed to enable using Blazor WebAssembly in restrictive network environments. Webcil files use a standard WebAssembly wrapper, where the assemblies are deployed as WebAssembly files that use the standard.wasm file extension.
Webcil is the default packaging format when you publish a Blazor WebAssembly app. To disable the use of Webcil, set the following MSBuild property in the app's project file:
<PropertyGroup> <WasmEnableWebcil>false</WasmEnableWebcil></PropertyGroup>Customize how boot resources are loaded using theloadBootResource API. For more information, seeASP.NET Core Blazor startup.
When a Blazor WebAssembly app is published, the output is statically compressed during publish to reduce the app's size and remove the overhead for runtime compression. The following compression algorithms are used:
Blazor relies on the host to serve the appropriate compressed files. When hosting a Blazor WebAssembly standalone app, additional work might be required to ensure that statically-compressed files are served:
Blazor relies on the host to serve the appropriate compressed files. When using anASP.NET Core Hosted Blazor WebAssembly project, the host project is capable of performing content negotiation and serving the statically-compressed files. When hosting a Blazor WebAssembly standalone app, additional work might be required to ensure that statically-compressed files are served:
web.config compression configuration, see theIIS: Brotli and Gzip compression section.Obtain the JavaScript Brotli decoder from thegoogle/brotli GitHub repository. The minified decoder file is nameddecode.min.js and found in the repository'sjs folder.
Note
If the minified version of thedecode.js script (decode.min.js) fails, try using the unminified version (decode.js) instead.
Update the app to use the decoder.
In thewwwroot/index.html file, setautostart tofalse on Blazor's<script> tag:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>After Blazor's<script> tag and before the closing</body> tag, add the following JavaScript code<script> block. The following function callsfetch withcache: 'no-cache' to keep the browser's cache updated.
Blazor Web App:
<script type="module"> import { BrotliDecode } from './decode.min.js'; Blazor.start({ webAssembly: { loadBootResource: function (type, name, defaultUri, integrity) { if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration' && type !== 'manifest') { return (async function () { const response = await fetch(defaultUri + '.br', { cache: 'no-cache' }); if (!response.ok) { throw new Error(response.statusText); } const originalResponseBuffer = await response.arrayBuffer(); const originalResponseArray = new Int8Array(originalResponseBuffer); const decompressedResponseArray = BrotliDecode(originalResponseArray); const contentType = type === 'dotnetwasm' ? 'application/wasm' : 'application/octet-stream'; return new Response(decompressedResponseArray, { headers: { 'content-type': contentType } }); })(); } } } });</script>Standalone Blazor WebAssembly:
<script type="module"> import { BrotliDecode } from './decode.min.js'; Blazor.start({ loadBootResource: function (type, name, defaultUri, integrity) { if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration') { return (async function () { const response = await fetch(defaultUri + '.br', { cache: 'no-cache' }); if (!response.ok) { throw new Error(response.statusText); } const originalResponseBuffer = await response.arrayBuffer(); const originalResponseArray = new Int8Array(originalResponseBuffer); const decompressedResponseArray = BrotliDecode(originalResponseArray); const contentType = type === 'dotnetwasm' ? 'application/wasm' : 'application/octet-stream'; return new Response(decompressedResponseArray, { headers: { 'content-type': contentType } }); })(); } } });</script>For more information on loading boot resources, seeASP.NET Core Blazor startup.
To disable compression, add theCompressionEnabled MSBuild property to the app's project file and set the value tofalse:
<PropertyGroup> <CompressionEnabled>false</CompressionEnabled></PropertyGroup>TheCompressionEnabled property can be passed to thedotnet publish command with the following syntax in a command shell:
dotnet publish -p:CompressionEnabled=falseTo disable compression, add theBlazorEnableCompression MSBuild property to the app's project file and set the value tofalse:
<PropertyGroup> <BlazorEnableCompression>false</BlazorEnableCompression></PropertyGroup>TheBlazorEnableCompression property can be passed to thedotnet publish command with the following syntax in a command shell:
dotnet publish -p:BlazorEnableCompression=falseRouting requests for page components in a Blazor WebAssembly app isn't as straightforward as routing requests in a Blazor Server app. Consider a Blazor WebAssembly app with two components:
Main.razor: Loads at the root of the app and contains a link to theAbout component (href="About").About.razor:About component.When the app's default document is requested using the browser's address bar (for example,https://www.contoso.com/):
index.html.index.html bootstraps the app.Main component is rendered.In the Main page, selecting the link to theAbout component works on the client because the Blazor router stops the browser from making a request on the Internet towww.contoso.com forAbout and serves the renderedAbout component itself. All of the requests for internal endpointswithin the Blazor WebAssembly app work the same way: Requests don't trigger browser-based requests to server-hosted resources on the Internet. The router handles the requests internally.
If a request is made using the browser's address bar forwww.contoso.com/About, the request fails. No such resource exists on the app's Internet host, so a404 - Not Found response is returned.
Because browsers make requests to Internet-based hosts for client-side pages, web servers and hosting services must rewrite all requests for resources not physically on the server to theindex.html page. Whenindex.html is returned, the app's Blazor router takes over and responds with the correct resource.
When deploying to an IIS server, you can use the URL Rewrite Module with the app's publishedweb.config file. For more information, seeHost and deploy ASP.NET Core Blazor WebAssembly with IIS.
Ahosted deployment serves the Blazor WebAssembly app to browsers from anASP.NET Core app that runs on a web server.
The client Blazor WebAssembly app is published into the/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot folder of the server app, along with any other static web assets of the server app. The two apps are deployed together. A web server that is capable of hosting an ASP.NET Core app is required. For a hosted deployment, Visual Studio includes theBlazor WebAssembly App project template (blazorwasm template when using thedotnet new command) with theHosted option selected (-ho|--hosted when using thedotnet new command).
For more information, see the following articles:
To deploy a hosted Blazor WebAssembly app as aframework-dependent executable for a specific platform (not self-contained) use the following guidance based on the tooling in use.
Aself-contained deployment is configured for a generated publish profile (.pubxml). Confirm that theServer project's publish profile contains the<SelfContained> MSBuild property set tofalse.
In the.pubxml publish profile file in theServer project'sProperties folder:
<SelfContained>false</SelfContained>Set theRuntime Identifier (RID) using theTarget Runtime setting in theSettings area of thePublish UI, which generates the<RuntimeIdentifier> MSBuild property in the publish profile:
<RuntimeIdentifier>{RID}</RuntimeIdentifier>In the preceding configuration, the{RID} placeholder is theRuntime Identifier (RID).
Publish theServer project in theRelease configuration.
Note
It's possible to publish an app with publish profile settings using the .NET CLI by passing/p:PublishProfile={PROFILE} to thedotnet publish command, where the{PROFILE} placeholder is the profile. For more information, see thePublish profiles andFolder publish example sections in theVisual Studio publish profiles (.pubxml) for ASP.NET Core app deployment article. If you pass the RID in thedotnet publish command and not in the publish profile, use the MSBuild property (/p:RuntimeIdentifier) with the command, not with the-r|--runtime option.
Configure aself-contained deployment by placing the<SelfContained> MSBuild property in a<PropertyGroup> in theServer project's project file set tofalse:
<SelfContained>false</SelfContained>Important
TheSelfContained property must be placed in theServer project's project file. The property can't be set correctly with thedotnet publish command using the--no-self-contained option or the MSBuild property/p:SelfContained=false.
Set theRuntime Identifier (RID) usingeither of the following approaches:
Option 1: Set the RID in a<PropertyGroup> in theServer project's project file:
<RuntimeIdentifier>{RID}</RuntimeIdentifier>In the preceding configuration, the{RID} placeholder is theRuntime Identifier (RID).
Publish the app in the Release configuration from theServer project:
dotnet publish -c ReleaseOption 2: Pass the RID in thedotnet publish command as the MSBuild property (/p:RuntimeIdentifier), not with the-r|--runtime option:
dotnet publish -c Release /p:RuntimeIdentifier={RID}In the preceding command, the{RID} placeholder is theRuntime Identifier (RID).
For more information, see the following articles:
Astandalone deployment serves the Blazor WebAssembly app as a set of static files that are requested directly by clients. Any static file server is able to serve the Blazor app.
Standalone deployment assets are published into either the/bin/Release/{TARGET FRAMEWORK}/publish/wwwroot orbin/Release/{TARGET FRAMEWORK}/browser-wasm/publish folder, where the{TARGET FRAMEWORK} placeholder is the target framework.
Blazor WebAssembly apps can be deployed to Azure App Services on Windows, which hosts the app on IIS.
Deploying a standalone Blazor WebAssembly app to Azure App Service for Linux isn't currently supported. We recommend hosting a standalone Blazor WebAssembly app usingAzure Static Web Apps, which supports this scenario.
A standalone Blazor WebAssembly app is published as a set of static files for hosting by a static file server.
To host the app in Docker:
publish folder assets to a location folder defined in the web server for serving static files.For configuration guidance, see the following resources:
Blazor WebAssembly apps can accept the following host configuration values as command-line arguments at runtime in the development environment.
The--contentroot argument sets the absolute path to the directory that contains the app's content files (content root). In the following examples,/content-root-path is the app's content root path.
Pass the argument when running the app locally at a command prompt. From the app's directory, execute:
dotnet watch --contentroot=/content-root-pathAdd an entry to the app'slaunchSettings.json file in theIIS Express profile. This setting is used when the app is run with the Visual Studio Debugger and from a command prompt withdotnet watch (ordotnet run).
"commandLineArgs": "--contentroot=/content-root-path"In Visual Studio, specify the argument inProperties >Debug >Application arguments. Setting the argument in the Visual Studio property page adds the argument to thelaunchSettings.json file.
--contentroot=/content-root-pathThe--pathbase argument sets the app base path for an app run locally with a non-root relative URL path (the<base> taghref is set to a path other than/ for staging and production). In the following examples,/relative-URL-path is the app's path base. For more information, seeASP.NET Core Blazor app base path.
Important
Unlike the path provided tohref of the<base> tag, don't include a trailing slash (/) when passing the--pathbase argument value. If the app base path is provided in the<base> tag as<base href="/CoolApp/"> (includes a trailing slash), pass the command-line argument value as--pathbase=/CoolApp (no trailing slash).
Pass the argument when running the app locally at a command prompt. From the app's directory, execute:
dotnet watch --pathbase=/relative-URL-pathAdd an entry to the app'slaunchSettings.json file in theIIS Express profile. This setting is used when running the app with the Visual Studio Debugger and from a command prompt withdotnet watch (ordotnet run).
"commandLineArgs": "--pathbase=/relative-URL-path"In Visual Studio, specify the argument inProperties >Debug >Application arguments. Setting the argument in the Visual Studio property page adds the argument to thelaunchSettings.json file.
--pathbase=/relative-URL-pathFor more information, seeASP.NET Core Blazor app base path.
The--urls argument sets the IP addresses or host addresses with ports and protocols to listen on for requests.
Pass the argument when running the app locally at a command prompt. From the app's directory, execute:
dotnet watch --urls=http://127.0.0.1:0Add an entry to the app'slaunchSettings.json file in theIIS Express profile. This setting is used when running the app with the Visual Studio Debugger and from a command prompt withdotnet watch (ordotnet run).
"commandLineArgs": "--urls=http://127.0.0.1:0"In Visual Studio, specify the argument inProperties >Debug >Application arguments. Setting the argument in the Visual Studio property page adds the argument to thelaunchSettings.json file.
--urls=http://127.0.0.1:0Blazor performs Intermediate Language (IL) trimming on each Release build to remove unnecessary IL from the output assemblies. For more information, seeConfigure the Trimmer for ASP.NET Core Blazor.
Blazor performs Intermediate Language (IL) linking on each Release build to remove unnecessary IL from the output assemblies. For more information, seeConfigure the Linker for ASP.NET Core Blazor.
This section applies to .NET 5 through .NET 7. In .NET 8 or later, .NET assemblies are deployed as WebAssembly files (.wasm) using the Webcil file format.
If a firewall, anti-virus program, or network security appliance is blocking the transmission of the app's dynamic-link library (DLL) files (.dll), you can follow the guidance in this section to change the file name extensions of the app's published DLL files.
Changing the file name extensions of the app's DLL files might not resolve the problem because many security systems scan the content of the app's files, not merely check file extensions.
For a more robust approach in environments that block the download and execution of DLL files, takeeither of the following approaches:
.wasm) using theWebcil file format. For more information, see theWebcil packaging format for .NET assemblies section in a .NET 8 or later version of this article.Third-party approaches exist for dealing with this problem. For more information, see the resources atAwesome Blazor.
After publishing the app, use a shell script or DevOps build pipeline to rename.dll files to use a different file extension in the directory of the app's published output.
In the following examples:
.dll files are renamed to use the.bin file extension from the command line..dll file extension are updated to the.bin file extension..dll files listed in theservice-worker-assets.js file to the.bin file extension.To use a different file extension than.bin, replace.bin in the following commands with the desired file extension.
In the following commands, the{PATH} placeholder is the path to the published_framework folder in thepublish folder.
Rename file extensions in the folder:
dir {PATH} | rename-item -NewName { $_.name -replace ".dll\b",".bin" }Rename file extensions in theblazor.boot.json file:
((Get-Content {PATH}\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\blazor.boot.jsonIf service worker assets are also in use because the app is aProgressive Web App (PWA):
((Get-Content {PATH}\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\service-worker-assets.jsIn the preceding command, the{PATH} placeholder is the path to the publishedservice-worker-assets.js file.
To address the compressedblazor.boot.json file, adopt either of the following approaches:
blazor.boot.json file, producing newblazor.boot.json.gz andblazor.boot.json.br files. (Recommended)blazor.boot.json.gz andblazor.boot.json.br files. (Compression is disabled with this approach.)For aProgressive Web App (PWA)'s compressedservice-worker-assets.js file, adopt either of the following approaches:
service-worker-assets.js file, producing newservice-worker-assets.js.br andservice-worker-assets.js.gz files. (Recommended)service-worker-assets.js.gz andservice-worker-assets.js.br files. (Compression is disabled with this approach.)To automate the extension change on Windows in .NET 6/7, the following approach uses a PowerShell script placed at the root of the project. The following script, which disables compression, is the basis for further modification if you wish to recompress theblazor.boot.json file andservice-worker-assets.js file if the app is aProgressive Web App (PWA). The path to thepublish folder is passed to the script when it's executed.
ChangeDLLExtensions.ps1::
param([string]$filepath)dir $filepath\wwwroot\_framework | rename-item -NewName { $_.name -replace ".dll\b",".bin" }((Get-Content $filepath\wwwroot\_framework\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\wwwroot\_framework\blazor.boot.jsonRemove-Item $filepath\wwwroot\_framework\blazor.boot.json.gzRemove-Item $filepath\wwwroot\_framework\blazor.boot.json.brIf service worker assets are also in use because the app is aProgressive Web App (PWA), add the following commands:
((Get-Content $filepath\wwwroot\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\wwwroot\service-worker-assets.jsRemove-Item $filepath\wwwroot\service-worker-assets.js.gzRemove-Item $filepath\wwwroot\service-worker-assets.js.brIn the project file, the script is executed after publishing the app for theRelease configuration:
<Target Name="ChangeDLLFileExtensions" AfterTargets="AfterPublish" Condition="'$(Configuration)'=='Release'"> <Exec Command="powershell.exe -command "& {.\ChangeDLLExtensions.ps1 '$(SolutionDir)'}"" /></Target>After publishing the app, manually recompressblazor.boot.json, andservice-worker-assets.js if used, to re-enable compression.
Note
When renaming and lazy loading the same assemblies, see the guidance inLazy load assemblies in ASP.NET Core Blazor WebAssembly.
Usually, the app's server requires static asset configuration to serve the files with the updated extension. For an app hosted by IIS, add a MIME map entry (<mimeMap>) for the new file extension in the static content section (<staticContent>) in a customweb.config file. The following example assumes that the file extension is changed from.dll to.bin:
<staticContent> ... <mimeMap fileExtension=".bin" mimeType="application/octet-stream" /> ...</staticContent>Include an update for compressed files ifcompression is in use:
<mimeMap fileExtension=".bin.br" mimeType="application/octet-stream" /><mimeMap fileExtension=".bin.gz" mimeType="application/octet-stream" />Remove the entry for the.dll file extension:
- <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />Remove entries for compressed.dll files ifcompression is in use:
- <mimeMap fileExtension=".dll.br" mimeType="application/octet-stream" />- <mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />For more information on customweb.config files, see theUse of a customweb.config section.
Typically on deployment:
In rare cases, lingering files from a prior deployment can corrupt a new deployment. Completely deleting the existing deployment (or locally-published app prior to deployment) may resolve the issue with a corrupted deployment. Often, deleting the existing deploymentonce is sufficient to resolve the problem, including for a DevOps build and deploy pipeline.
If you determine that clearing a prior deployment is always required when a DevOps build and deploy pipeline is in use, you can temporarily add a step to the build pipeline to delete the prior deployment for each new deployment until you troubleshoot the exact cause of the corruption.
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?