Skip to content

Commit 4b31efd

Browse files
committed
[Pre4] Blazor WASM performance profiling
1 parent 0ba3006 commit 4b31efd

File tree

22 files changed

+515
-256
lines changed

22 files changed

+515
-256
lines changed

aspnetcore/blazor/components/event-handling.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ It's often convenient to close over additional values using C# method parameters
577577

578578
:::moniker-end
579579

580-
Creating a large number of event delegates in a loop may cause poor rendering performance. For more information, see <xref:blazor/performance#avoid-recreating-delegates-for-many-repeated-elements-or-components>.
580+
Creating a large number of event delegates in a loop may cause poor rendering performance. For more information, see <xref:blazor/performance/rendering#avoid-recreating-delegates-for-many-repeated-elements-or-components>.
581581

582582
Avoid using a loop variable directly in a lambda expression, such as `i` in the preceding `for` loop example. Otherwise, the same variable is used by all lambda expressions, which results in use of the same value in all lambdas. Capture the variable's value in a local variable. In the preceding example:
583583

aspnetcore/blazor/components/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ You can factor out child components purely as a way of reusing rendering logic.
13921392
}
13931393
```
13941394

1395-
For more information, see [Reuse rendering logic](xref:blazor/performance#define-reusable-renderfragments-in-code).
1395+
For more information, see [Reuse rendering logic](xref:blazor/performance/rendering#define-reusable-renderfragments-in-code).
13961396

13971397
## Loop variables with component parameters and child content
13981398

aspnetcore/blazor/components/lifecycle.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ If a disposable component doesn't use a <xref:System.Threading.CancellationToken
326326

327327
For more information on route parameters and constraints, see <xref:blazor/fundamentals/routing>.
328328

329-
For an example of implementing `SetParametersAsync` manually to improve performance in some scenarios, see <xref:blazor/performance#implement-setparametersasync-manually>.
329+
For an example of implementing `SetParametersAsync` manually to improve performance in some scenarios, see <xref:blazor/performance/rendering#implement-setparametersasync-manually>.
330330

331331
## After component render (`OnAfterRender{Async}`)
332332

aspnetcore/blazor/components/rendering.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Components inherited from <xref:Microsoft.AspNetCore.Components.ComponentBase> s
3939

4040
In most cases, <xref:Microsoft.AspNetCore.Components.ComponentBase> conventions result in the correct subset of component rerenders after an event occurs. Developers aren't usually required to provide manual logic to tell the framework which components to rerender and when to rerender them. The overall effect of the framework's conventions is that the component receiving an event rerenders itself, which recursively triggers rerendering of descendant components whose parameter values may have changed.
4141

42-
For more information on the performance implications of the framework's conventions and how to optimize an app's component hierarchy for rendering, see <xref:blazor/performance#optimize-rendering-speed>.
42+
For more information on the performance implications of the framework's conventions and how to optimize an app's component hierarchy for rendering, see <xref:blazor/performance/rendering>.
4343

4444
::: moniker range=">= aspnetcore-8.0"
4545

@@ -147,7 +147,7 @@ Even if <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> is
147147

148148
::: moniker-end
149149

150-
For more information on performance best practices pertaining to <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A>, see <xref:blazor/performance#avoid-unnecessary-rendering-of-component-subtrees>.
150+
For more information on performance best practices pertaining to <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A>, see <xref:blazor/performance/rendering#avoid-unnecessary-rendering-of-component-subtrees>.
151151

152152
## `StateHasChanged`
153153

aspnetcore/blazor/components/templated-components.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,6 @@ Without using the `@key` directive attribute in the `TableTemplate` component, t
329329

330330
## Additional resources
331331

332-
* <xref:blazor/performance#define-reusable-renderfragments-in-code>
332+
* <xref:blazor/performance/rendering#define-reusable-renderfragments-in-code>
333333
* <xref:blazor/components/key>
334334
* [Blazor samples GitHub repository (`dotnet/blazor-samples`)](https://github.com/dotnet/blazor-samples) ([how to download](xref:blazor/fundamentals/index#sample-apps))

aspnetcore/blazor/globalization-localization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ Adopting [invariant globalization](#invariant-globalization) only results in usi
143143
```
144144

145145
> [!NOTE]
146-
> [`<BlazorEnableTimeZoneSupport>`](xref:blazor/performance#disable-unused-features) overrides an earlier `<InvariantTimezone>` setting. We recommend removing the `<BlazorEnableTimeZoneSupport>` setting.
146+
> [`<BlazorEnableTimeZoneSupport>`](xref:blazor/performance/app-download-size#disable-unused-features) overrides an earlier `<InvariantTimezone>` setting. We recommend removing the `<BlazorEnableTimeZoneSupport>` setting.
147147
148148
:::moniker-end
149149

aspnetcore/blazor/host-and-deploy/configure-linker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,4 @@ For more information, see [I18N: Pnetlib Internationalization Framework Library
119119

120120
## Additional resources
121121

122-
* <xref:blazor/performance#intermediate-language-il-linking>
122+
<xref:blazor/performance/app-download-size#intermediate-language-il-linking>

aspnetcore/blazor/host-and-deploy/configure-trimmer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,4 @@ Because custom types are never trimmed by Blazor when an app is published, the c
178178
## Additional resources
179179

180180
* [Trim self-contained deployments and executables](/dotnet/core/deploying/trimming/trim-self-contained)
181-
* <xref:blazor/performance#intermediate-language-il-trimming>
181+
* <xref:blazor/performance/app-download-size#intermediate-language-il-trimming>

aspnetcore/blazor/javascript-interoperability/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Further JS interop guidance is provided in the following articles:
1818

1919
* <xref:blazor/js-interop/call-javascript-from-dotnet>
2020
* <xref:blazor/js-interop/call-dotnet-from-javascript>
21+
* <xref:blazor/performance/js-interop>
2122

2223
:::moniker range=">= aspnetcore-7.0"
2324

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
title: ASP.NET Core Blazor app download size performance best practices
3+
author: guardrex
4+
description: Tips for reducing app download size in ASP.NET Core Blazor apps and avoiding common performance problems.
5+
monikerRange: '>= aspnetcore-3.1'
6+
ms.author: riande
7+
ms.custom: mvc
8+
ms.date: 04/16/2025
9+
uid: blazor/performance/app-download-size
10+
---
11+
# ASP.NET Core Blazor app download size performance best practices
12+
13+
[!INCLUDE[](~/includes/not-latest-version.md)]
14+
15+
:::moniker range=">= aspnetcore-6.0"
16+
17+
## Runtime relinking
18+
19+
For information on how runtime relinking minimizes an app's download size, see <xref:blazor/tooling/webassembly#runtime-relinking>.
20+
21+
:::moniker-end
22+
23+
## Use `System.Text.Json`
24+
25+
Blazor's JS interop implementation relies on <xref:System.Text.Json>, which is a high-performance JSON serialization library with low memory allocation. Using <xref:System.Text.Json> shouldn't result in additional app payload size over adding one or more alternate JSON libraries.
26+
27+
For migration guidance, see [How to migrate from `Newtonsoft.Json` to `System.Text.Json`](/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to).
28+
29+
## Intermediate Language (IL) trimming
30+
31+
*This section only applies to client-side Blazor scenarios.*
32+
33+
:::moniker range=">= aspnetcore-5.0"
34+
35+
Trimming unused assemblies from a Blazor WebAssembly app reduces the app's size by removing unused code in the app's binaries. For more information, see <xref:blazor/host-and-deploy/configure-trimmer>.
36+
37+
:::moniker-end
38+
39+
:::moniker range="< aspnetcore-5.0"
40+
41+
[Linking a Blazor WebAssembly app](xref:blazor/host-and-deploy/configure-linker) reduces the app's size by trimming unused code in the app's binaries. The Intermediate Language (IL) Linker is only enabled when building in `Release` configuration. To benefit from this, publish the app for deployment using the [`dotnet publish`](/dotnet/core/tools/dotnet-publish) command with the [-c|--configuration](/dotnet/core/tools/dotnet-publish#options) option set to `Release`:
42+
43+
```dotnetcli
44+
dotnet publish -c Release
45+
```
46+
47+
:::moniker-end
48+
49+
## Lazy load assemblies
50+
51+
*This section only applies to client-side Blazor scenarios.*
52+
53+
Load assemblies at runtime when the assemblies are required by a route. For more information, see <xref:blazor/webassembly-lazy-load-assemblies>.
54+
55+
## Compression
56+
57+
*This section only applies to Blazor WebAssembly apps.*
58+
59+
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. Blazor relies on the server to perform content negotiation and serve statically-compressed files.
60+
61+
After an app is deployed, verify that the app serves compressed files. Inspect the **Network** tab in a browser's [developer tools](https://developer.mozilla.org/docs/Glossary/Developer_Tools) and verify that the files are served with `Content-Encoding: br` (Brotli compression) or `Content-Encoding: gz` (Gzip compression). If the host isn't serving compressed files, follow the instructions in <xref:blazor/host-and-deploy/webassembly/index#compression>.
62+
63+
## Disable unused features
64+
65+
*This section only applies to client-side Blazor scenarios.*
66+
67+
Blazor WebAssembly's runtime includes the following .NET features that can be disabled for a smaller payload size.
68+
69+
Blazor WebAssembly carries globalization resources required to display values, such as dates and currency, in the user's culture. If the app doesn't require localization, you may [configure the app to support the invariant culture](xref:blazor/globalization-localization#invariant-globalization), which is based on the `en-US` culture.
70+
71+
:::moniker range=">= aspnetcore-8.0"
72+
73+
Adopting [invariant globalization](xref:blazor/globalization-localization#invariant-globalization) only results in using non-localized timezone names. To trim timezone code and data from the app, apply the `<InvariantTimezone>` MSBuild property with a value of `true` in the app's project file:
74+
75+
```xml
76+
<PropertyGroup>
77+
<InvariantTimezone>true</InvariantTimezone>
78+
</PropertyGroup>
79+
```
80+
81+
> [!NOTE]
82+
> [`<BlazorEnableTimeZoneSupport>`](xref:blazor/performance/app-download-size#disable-unused-features) overrides an earlier `<InvariantTimezone>` setting. We recommend removing the `<BlazorEnableTimeZoneSupport>` setting.
83+
84+
:::moniker-end
85+
86+
:::moniker range="< aspnetcore-8.0"
87+
88+
A data file is included to make timezone information correct. If the app doesn't require this feature, consider disabling it by setting the `<BlazorEnableTimeZoneSupport>` MSBuild property to `false` in the app's project file:
89+
90+
```xml
91+
<PropertyGroup>
92+
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
93+
</PropertyGroup>
94+
```
95+
96+
:::moniker-end
97+
98+
:::moniker range="< aspnetcore-5.0"
99+
100+
Collation information is included to make APIs such as <xref:System.StringComparison.InvariantCultureIgnoreCase?displayProperty=nameWithType> work correctly. If you're certain that the app doesn't require the collation data, consider disabling it by setting the `BlazorWebAssemblyPreserveCollationData` MSBuild property in the app's project file to `false`:
101+
102+
```xml
103+
<PropertyGroup>
104+
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
105+
</PropertyGroup>
106+
```
107+
108+
:::moniker-end

0 commit comments

Comments
 (0)