-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Influence HTML head from Blazor #23833
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
This is a great start. Thanks @MackinnonBuck! A couple of thoughts:
|
Thanks for the feedback, @SteveSandersonMS! My main reason for adding |
The link element can be used for a number of other link types such as rel="icon" that are not body-ok types. |
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 discussed removing special code paths for prerendering and yoloing it all the time. This should remove the dependency on Server.Circuits from this project.
src/Components/Web.Extensions/src/HeadManagement/TitleElement.cs
Outdated
Show resolved
Hide resolved
protected override void OnInitialized() | ||
{ | ||
_headManager = ServiceProvider.GetHeadManager() ?? | ||
throw new InvalidOperationException($"{GetType()} requires a {typeof(HeadManager)} service."); |
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.
@SteveSandersonMS \ @javiercn, would we consider having a way for Inject
to tell you what to do to fix this?
[Inject(Error = "Did you forget to invoke AddBlah()?")]
It shouldn't be too much work to include that in the diagnostics here:
throw new InvalidOperationException($"Cannot provide a value for property " + |
if (grandchildrenArray) { | ||
while (grandchildrenArray.length > 0) { | ||
removeLogicalChild(childToRemove, 0); | ||
} |
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.
This is interesting. Was there a bug before? What scenario triggered it?
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 encountered a bug where grandchildrenArray
was undefined if a component rendered a comment during prerendering.
src/Components/Web.Extensions/src/HeadManagement/HeadManagementJSRuntimeExtensions.cs
Show resolved
Hide resolved
src/Components/Web.Extensions/src/HeadManagement/HeadManagementJSRuntimeExtensions.cs
Show resolved
Hide resolved
src/Components/Web.Extensions/src/HeadManagement/HeadManagementRenderTreeBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
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.
This looks great. Could you rebase this on to the release/5.0-preview8 branch?
src/Components/Web.Extensions/src/HeadManagement/HeadTagBase.cs
Outdated
Show resolved
Hide resolved
src/Components/Web.Extensions/src/WebExtensionsServiceCollectionExtensions.cs
Outdated
Show resolved
Hide resolved
src/Components/Web.Extensions/src/HeadManagement/HeadManagementRenderTreeBuilderExtensions.cs
Outdated
Show resolved
Hide resolved
b71849d
to
29d5a71
Compare
src/Components/Web.Extensions/src/Microsoft.AspNetCore.Components.Web.Extensions.csproj
Outdated
Show resolved
Hide resolved
src/Components/test/testassets/BasicTestApp/ModifyHeadComponent.razor
Outdated
Show resolved
Hide resolved
<p> | ||
Meta:<br /> | ||
<input id="input-meta-binding" @bind="metaContent" placeholder="Set the meta content" /> | ||
<Meta id="meta-with-bindings" content="@metaContent" /> |
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.
What's the IDE experience with this? We've had problems in the past with Components that overlapped with HTML tag names, since Meta is a valid HTML5 tag (they are case-insensitive)
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.
It's a good point. Based on experiences with <Button>
/<button>
, it seems likely that VS may interfere with typing <Title>
and try to auto-correct it to <title>
.
While this is annoying, I don't think we should block the PR on it, because there isn't a great alternative right now, and developers can self-correct this, and eventually the IDE can do a better job with it.
Also a better solution still would be if we implemented #22194. Then it would be possible for people not to have a @using
directive for the full namespace here, but instead type things like:
<Head.Title>My title</Head.Title>
However that would only work if the namespaces containing these elements was something like Microsoft.AspNetCore.Components.Web.Extensions.Head
.
Do you think it might be worth putting them in that namespace proactively so that we can get this developer experience eventually when #22194 is implemented? In the short term developers will still get the same experience of typing <Title>Hey</Title>
as long as they have a @using
for the full namespace. This also fixes one other small concern I had that these component names are super-generic and people might have their own reasons for creating unrelated components called <Title>
/<Link>
etc.
Interested in opinions from @javiercn as well as @MackinnonBuck here!
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 agree with @SteveSandersonMS's suggestion to proactively put the components in a Head
namespace. It would make good use of #22194 (when implemented) without making the current user experience worse.
src/Components/test/E2ETest/ServerExecutionTests/PrerenderingTest.cs
Outdated
Show resolved
Hide resolved
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 have some minor comments, but overall looks great!
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.
Fantastic work, @MackinnonBuck! This looks great to me.
As with @javiercn there are a couple of remaining small comments but hopefully this should be able to merge really soon.
…etcore into t-mabuc/influence-head
@MackinnonBuck I'm sorry to bother you, but I've browsed this PR and haven't found an answer: how is the prerendering actually working here? From what I see, there are only comments added to the render tree, and all actual DOM work is done in JavaScript. Is JS being run now as part of prerender? I ask because in the #10450 there was some talk about using such a feature for impacting social previews. Would such scenario be covered by this PR? |
@amis92 the way it works is during prerendering the content gets emitted as a comment into the DOM and then a small piece of JS updates it when the page loads on the browser. |
Ah. So no game, then. It's not actually prerendered for static HTML processing like link previews on websites. |
Fantastic, this PR adds just the thing I was looking for :D Seeing that this PR was merged into https://github.com/dotnet/aspnetcore/tree/release/5.0-preview8, I assumed I would be able to find it on the aspnetcore preview feed in the Any pointers on where I might try these things out (ideally using a package feed)? |
Typical. I did one more attempt at finding it after writing the above, and of course I found it. I was looking on the Installed tab in Visual Studio rather than on the Browse tab 😅 One day I'll get the hang of this VS NuGet UI 🤞 |
Summary of the changes
Title
component to modify the document title.Meta
component to add or modifymeta
tags.Link
component.Implementation details
I've changed my implementation to be simpler at the cost of some functionality. If users request additional functionality, we should consider taking pieces from this.
Usage sample:
Note that these components don't require a surrounding
Head
component.Addresses #10450