-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Razor compiler emit CSS scope attributes #23703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
I've also added a further optimization into the "minimized attribute" code path, because this becomes an extremely-frequently hit path for components that have scoped CSS. On components with scoped CSS, every single HTML element has at least one minimized attribute. The FastGrid-from-blank benchmark improves by around 5% due to this optimization. Admittedly that's a pretty extreme case, but it is the sort of thing we're trying to optimize. |
src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDesignTimeNodeWriter.cs
Show resolved
Hide resolved
| /// <param name="file">The <see cref="FileInfo"/>.</param> | ||
| public DefaultRazorProjectItem(string basePath, string filePath, string relativePhysicalPath, string fileKind, FileInfo file) | ||
| /// <param name="cssScope">A scope identifier that will be used on elements in the generated class, or null.</param> | ||
| public DefaultRazorProjectItem(string basePath, string filePath, string relativePhysicalPath, string fileKind, FileInfo file, string cssScope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do string cssScope = null here to make this backwards compatible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but the class is internal so hopefully we don’t need to be concerned with back-compat.
src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorProjectEngine.cs
Show resolved
Hide resolved
| { | ||
| public RenderTreeBuilder() { } | ||
| public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { } | ||
| public void AddAttribute(int sequence, string name) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a perf optimization?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I answered my own question here. You can correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes: #23703 (comment)
javiercn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not an expert, but the changes and the tests look good!
|
Thanks @javiercn. I'd like to get a sign-off from either @NTaylorMullen or @ajaybhargavb before I merge it though! |
Sounds reasonable :) |
src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorProjectItem.cs
Show resolved
Hide resolved
|
Pinging @NTaylorMullen @ajaybhargavb - do my answers above sound right to you? |
I have the same question as @NTaylorMullen's comment above. Otherwise consider me signed off as long as @NTaylorMullen is happy. One other comment,
|
I posted an answer previously. Is there still an open question? If so, could you clarify what? |
The MSBuild targets are a separate work item, not implemented here. |
Woah. I swear GitHub hid your response from me 👀. That resolves my concerns |
|
Will this be compatible with MyComponent.razor.css files that are generated from scss files during build? |
| if (!string.IsNullOrEmpty(kind)) | ||
| { | ||
| builder.AppendLine("-k"); | ||
| builder.AppendLine(kind); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question not related to this PR but I noticed it while reviewing: @ajaybhargavb / @pranavkm given the IsNullOrEmpty check above if someone clears their DocumentKind for a Razor item wont that corrupt every other document kind because it will no longer be 1-to-1? I'd imagine if the parser version was >= 3 then we'd always output Kind even if it wasn't on the item to ensure the mappings were correct.
| if (CssScopeSources.Values.Count != CssScopeValues.Values.Count) | ||
| { | ||
| // CssScopeSources and CssScopeValues arguments must appear as matched pairs | ||
| Error.WriteLine($"{CssScopeSources.Description} has {CssScopeSources.Values.Count}, but {CssScopeValues.Description} has {CssScopeValues.Values.Count} values."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs
Outdated
Show resolved
Hide resolved
| Outputs = Option("-o", "Generated output file path", CommandOptionType.MultipleValue); | ||
| RelativePaths = Option("-r", "Relative path", CommandOptionType.MultipleValue); | ||
| FileKinds = Option("-k", "File kind", CommandOptionType.MultipleValue); | ||
| CssScopeSources = Option("-cssscopeinput", "CSS scope source file", CommandOptionType.MultipleValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cssscopeinput makes it sound like this is the CSS file. Ditto with the description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Changed cssscopeinput to cssscopedinput (to clarify that the scoping is something happening to the input, rather than the input being the scope), and updated descriptions. The term input here is still applicable because of its correspondence to the other parameter named input.
src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorProjectEngine.cs
Show resolved
Hide resolved
src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorProjectItem.cs
Show resolved
Hide resolved
…r minimized HTML attributes
8f8f7eb to
accc34a
Compare
Implements #22776
The actual IR tree update is pretty simple - we just add an extra attribute to every markup element within a component that has an associated CSS scope.
Most of the work here is plumbing the information from MSBuild through various layers within the Razor compiler. @NTaylorMullen @ajaybhargavb are you happy with the way this is being done here? It feels quite special-casey but it doesn't look like there's any other established way to pass through per-document parameters. I did consider passing this information via
RazorCodeGenerationOptionsbut that seems only to be used for project-wide settings so doesn't look right to use it for per-document information.Blazor team review notes: This PR means that our MSBuild code in the SDK can choose to supply
CssScopemetadata for any of theRazorComponentitemgroup entries. For example:... will end up rendering an extra attribute called
b-8d2ksdjwa20on each of its HTML elements (e.g.,<span b-8d2ksdjwa20>Hey</span>). This ties in with the CSS selector rewriting implemented in #23657 so that CSS rules only apply to elements rendered by this component.