Skip to content

Conversation

@SteveSandersonMS
Copy link
Member

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 RazorCodeGenerationOptions but 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 CssScope metadata for any of the RazorComponent itemgroup entries. For example:

    <Content Update="Pages\Counter.razor">
      <!-- TODO: In our SDK, auto-generate this metadata for any component that has a corresponding *.razor.css file on disk -->
      <!-- The exact value doesn't matter, but should be derived from a hash of the OS-independent relative path to the .razor file within the project -->
      <CssScope>b-8d2ksdjwa20</CssScope>
    </Content>

... will end up rendering an extra attribute called b-8d2ksdjwa20 on 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.

@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Jul 6, 2020
@ghost ghost added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Jul 6, 2020
@SteveSandersonMS
Copy link
Member Author

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.

/// <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)
Copy link
Member

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?

Copy link
Member Author

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.

@pranavkm pranavkm requested a review from a team July 6, 2020 22:30
{
public RenderTreeBuilder() { }
public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { }
public void AddAttribute(int sequence, string name) { }
Copy link
Member

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?

Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

@javiercn javiercn left a 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!

@SteveSandersonMS
Copy link
Member Author

Thanks @javiercn. I'd like to get a sign-off from either @NTaylorMullen or @ajaybhargavb before I merge it though!

@javiercn
Copy link
Member

javiercn commented Jul 8, 2020

Thanks @javiercn. I'd like to get a sign-off from either @NTaylorMullen or @ajaybhargavb before I merge it though!

Sounds reasonable :)

@SteveSandersonMS
Copy link
Member Author

Pinging @NTaylorMullen @ajaybhargavb - do my answers above sound right to you?

@ajaybhargavb
Copy link
Contributor

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 didn't see any Razor SDK tests that test the MSBuild portions etc. cc @pranavkm in case he has any thoughts on what to add here.

@SteveSandersonMS
Copy link
Member Author

I have the same question as @NTaylorMullen's comment above.

I posted an answer previously. Is there still an open question? If so, could you clarify what?

@SteveSandersonMS
Copy link
Member Author

I didn't see any Razor SDK tests that test the MSBuild portions etc.

The MSBuild targets are a separate work item, not implemented here.

@ajaybhargavb
Copy link
Contributor

I posted an answer previously. Is there still an open question? If so, could you clarify what?

Woah. I swear GitHub hid your response from me 👀. That resolves my concerns

@mrpmorris
Copy link

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);

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.");

Choose a reason for hiding this comment

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

👍

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);

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.

Copy link
Member Author

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.

@SteveSandersonMS SteveSandersonMS force-pushed the stevesa/rzc-emit-scope-attributes branch from 8f8f7eb to accc34a Compare July 13, 2020 14:35
@SteveSandersonMS SteveSandersonMS merged commit 90b697f into master Jul 13, 2020
@SteveSandersonMS SteveSandersonMS deleted the stevesa/rzc-emit-scope-attributes branch July 13, 2020 16:27
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 area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS isolation: Razor compiler update to emit CSS scope attributes

7 participants