In 3.x versions of Blazor Server and Blazor WebAssembly, .razor files preserved whitespace in the rendered output exactly (update: not exactly, see comment by @rynowak below).
However, one of our major goals for Blazor on .NET 5 is to improve performance, and our investigations determined that insignificant whitespace tree nodes consumed up to 40% of the rendering time in benchmarks. So, starting with .NET 5 preview 7, the .razor compiler will omit insignificant whitespace by default.
In the vast majority of cases, this will not have any effect on the visual layout of the rendered component, since the whitespace nodes being removed would not normally affect it. However, the whitespace might affect the rendered output if you are using a CSS rule like white-space: pre. If you need to preserve the whitespace, you can use the new directive @preservewhitespace true at the top of your .razor file, or inside an _Imports.razor file to apply the preference to an entire subdirectory or even your whole project.
For example, given the following .razor code:
<ul>
@foreach (var item in Items)
{
<li>
@item.Text
</li>
}
</ul>
This would previously have rendered two whitespace nodes outside the @foreach, and then two more around the <li>, and then two more around @item.Text. If the list contained 100 items, this would have been 402 whitespace nodes - i.e., more than half of all nodes rendered, even though none of them would visually affect the rendered output. Eliminating them at compile time greatly improves performance for rendering and diffing.
Can we extend this to have an option for Razor Pages and MVC Views as well ? It not only affect performance on the "diff" but also on payload, and since we are going to introduce the work already for blazor, I would be very happy if we can extend this to .cshtml files too.
The following question was posted elsewhere by @DustinKingen:
Does this affect the verbatim <text></text> tags?
<li>
<text> @item.Text</text>
</li>
The answer is that <text> is only a way of telling the compiler to transition from "code" compilation mode into "markup" compilation mode. You wouldn't use it within a <li> as in the example above, because the compiler already sees that as markup. You'd use it within a C# code block, and it wouldn't affect whitespace stripping at all.
Can we extend this to have an option for Razor Pages and MVC Views as well ?
Maybe - please file an issue if that interests you.
nitpick: the following is a filthy lie 😆
In 3.x versions of Blazor Server and Blazor WebAssembly, .razor files preserved whitespace in the rendered output exactly.
In 3.x version of Blazor whitespace in the text context was preserved. We would not have preserved whitespace inside a tag header (when rendering static HTML for components).
Example:
<foo bar="baz" />
If you did a "view source" you would not see that whitespace preserved, which is a difference from text-mode Razor.
@SteveSandersonMS - did you consider doing a "once and for all" to avoid the other breaking change that this introduces? (Is a @preservewhitespace now a reserved word?)
In the past we considered introducing an @pragma directive so that we don't have clashes with user code when introducing directives.
Yes, that’s a valid correction about whitespace within tags! Thanks. I was focused on dynamic rendering, not prerendering, when writing that description.
Yes, I did consider the more general purpose directive (I remember our discussions about it) but considered “preservewhitespace” to be a sufficiently unlikely symbol name that clashes would not be a realistic issue. Hence the idea of “pragma” gets kicked further down the road once more. If anyone’s interested in implementing “pragma” before 5.0 ships we could change the implementation to use that.
TBH the pragma idea might be nontrivial to design, as it seems like any combination of tokens might be required after it. I’m sure it could be done but I’m glad not to consider it in scope for this change.
TBH the pragma idea might be nontrivial to design, as it seems like any combination of tokens might be required after it. I’m sure it could be done but I’m glad not to consider it in scope for this change.
It wouldn't be so bad. Directive parsing is already data-driven (very little code gets written in the parser for a new directive).
Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.
This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!
Most helpful comment
The following question was posted elsewhere by @DustinKingen:
Does this affect the verbatim
<text></text>tags?The answer is that
<text>is only a way of telling the compiler to transition from "code" compilation mode into "markup" compilation mode. You wouldn't use it within a<li>as in the example above, because the compiler already sees that as markup. You'd use it within a C# code block, and it wouldn't affect whitespace stripping at all.Maybe - please file an issue if that interests you.