#494: Declarative Shadow DOM

Visit on Github.

Opened Apr 2, 2020

Hello TAG!

I'm requesting a TAG review of Declarative Shadow DOM.

A declarative API to allow the creation of #shadowroots using only HTML and no Javascript. This API allows Web Components that use Shadow DOM to also make use of Server-Side Rendering (SSR), to get rendered content onscreen quickly without requiring Javascript for shadow root attachment and population.

Further details:

  • I have reviewed the TAG's API Design Principles
  • The group where the incubation/design work on this is being done: WhatWG
  • The group where standardization of this work is intended to be done: WhatWG HTML spec
  • Existing major pieces of multi-stakeholder review or discussion of this design: https://github.com/whatwg/dom/issues/831
  • Major unresolved issues with or opposition to this design: Discussion is still underway, but we're mostly talking about smaller issues at this point.
  • This work is being funded by: Google / Chromium

We'd prefer the TAG provide feedback as:

☂️ open a single issue in our GitHub repo for the entire review

Discussions

2020-04-27

Minutes

David: Examples in the explainer look like they're non-reusable, i.e. it's less a template for components than an entire DOM tree some of which happens to be in shadow roots.

Tess: Right, this is intended as a very narrow feature to handle this sever-side rendering case, where they're serializing a server-side representation of the DOM, and it doesn't matter that they're repeating DOM.

... This isn't a general purpose solution for custom elements.

David: When I saw the title, I was hoping for something more...

... Reminds me of writing XBL and linking to it from CSS (though the linking to it from CSS was not great).. there were some nice things about that, I guess.

Tess: I need to read up and refresh my memory on this discussion, don't have time in this breakout so let's bump it a couple of weeks.

2020-05-11

Minutes

Alice: I've been asking them to flesh out the use cases more. The last comment confused me a litle. Let me see if I can summarize.

...: What is this for? It's for people using web components, to get things on the screen faster, to expose contents of shadow dom to search engines, also serialization and deserialization of DOM which has shadow DOM

...: CSS developers interested in style isolation but using a design system that prohibits JavaScript

Tess: Last point seems to be that there is no way to do style isolation other than Shadow DOM, which requires JS, and some design systems prohibit JS, so there is no way to do style isolation.

... Only reason they're using Shadow DOM is because of a missing feature in CSS. Not sure it makes sense to add this feature to Shadow DOM solely for this reason.

Alice: the serialization case didn't make sense to me either

Tess: Was imagining a third party... don't have fully worked out example. Non-coordinated serialisation and de-serialisation...

You're on a page, the page uses a component... you're the author of a tool that page embeds... the tool needs to serialise a chunk of DOM... would be nice to get a "innerHTML on steroids" and then ... do something ...

... Would need to be deserialised on a page that knew about the component.

Alice: Mason mentions "already hydrated" page for SSR - but would still need to re-attach event listeners.

... Raised concerns about the missing CSS feature, response was that we should fix the problems in Shadow DOM regardless.

Tess: Weird to me to pursue this just for style isolation... if style isolation is the motivation for this, why isn't that same motivation being used for style isolation?

... If we had style isolation as its own independent feature, that might impact the shape of this design. Might affect the syntax of what gets serialised. There might also be other lessons learned from that that might impact the design here.

Alice: Main question for me is how event listeners etc. get re-attached.

Tess: Are you going to end up in a weird state when trying to re-attach those event listeners?

Alice: Let's bump this to the F2F.

2020-06-08

Minutes

Alice: The one major issue is involving sending a lot of boilerplate content. Ex. shadow DOM content being created by UA compared to custom element needs to "hydrate". They imagine the shadow DOM content (inside the template) will be different every time. Suggested they find out if this is really true. Mason asked how they would go about finding it out. Ans: we don't know.

Peter: Seems like it wouldn't be hard to create a hybrid approach with custom element inside template.

Alice: Having nested shadow DOM is a problem because IDs can't be used from the light DOM. Also, what happens if you define a template shadow root and have the contents of it be referenced by another template that hasn't been processed yet. That's a pretty odd use of idref.

... Then Tess had a question about closed shadow roots.

Tess: Response was - it's impossible, which is good. It be great if they make it clear in the explainer.

Alice: Serialization of closed shadow root from outside.

Tess: If you get foo.innerHTML, and foo's child bar has a closed shadow tree, I thought that foo.innerHTML would include that. In their reply they said it wouldn't.

Peter: it is bad if it does serialize.

Alice: If you do server side rendering you'll have access to all shadow roots.

Peter: If you do element.innerHTML you'll get no shadow roots unless you pass the parameter asking about it. So the server can generate a document that contains the closed shadow roots. ... Is there a security implication of the server side being able to fetch() and get all closed shadow root?

Tess: It is as possible as before, so nothing new should be possible.

Alice: <template shadowroot="open" shadowrootdelegatesfocus>, we thought this was odd from usage point of view if there will be more options to attachShadow(). Proposed use of token list e.g. shadowrootoptions="delegatesfocus anotherbool someotherbool". The response was that ... slot assignment and we have to have all the bool parameters as one parameter and the rest as different attributes. ... I'm inclined to say that since there aren't any other arguments, it's a bit premature to suggest combining the other non-existent things.

Tess: SGTM

Peter: The only other way would be serializing to JSON etc.

Tess: At this point we really shouldn't be adding new microsyntaxes to HTML.

Alice: Last issue is - not allowing streaming into shadow root contents. Anything that has the style of <my-app> with a shadow root, nothing will show up until the entire document is parsed. ... (reading issue response). Bottom line, it's more difficult the implement. Once we see if/how this is causing issues to users there could be an option added allowing streaming. It seems quite reasonable to me.

Peter: Right, but it seems this will push even more complexity to the users.

David: What would be broken if implementations could do it either way and let it be a quality of implementation issue?

Peter: Guessing, one issue is scripts can be broken.

Alice: WRT pushing complexity to author, we can say they should think about adding the option now.

Tess: A little concerned about implementations that don't allow streaming, what would be net effect - error, silent error, nothing...?

Alice: What other options are there?

Tess: What if we have a flag for the not-streaming case? Want to preserve the default of streaming case being unmarked.

Peter: If streaming is something that you need to opt into, what happens if that's downloaded by a browser that doesn't support it?

Alice: That's where feature detection comes into play right.

Peter: I think Tess' point is worth exploring.

Alice: The problem is now framed better - 1. adding an option for it is adding work to authors while this option had to be default. 2. since this is coming later, can we make it detectable and handle it gracefully.

Peter: Well it could be done now if you define the feature from the get go but be explicit that implementations will be adding this later.

Alice: How do you detect it? Make it a readonly property?

Peter: That could work. ... If this is going to be eventually streamable it would be nice for authors to write the code that will be streamable now.

Rossen: I think adding future-proofing and pretending that streaming is there from the get go is more problematic than not having the feature now at all and evolving it later.

Alice: So the advice is - please think carefully about the additional complexity down the road that would be pushed to authors and possibly implementation (for those implementing from scratch). They should looking into how difficult is to have streaming by default now and if the opposite justifies the additional complexity in the future.

Peter: This is a bigger concern to me because without streaming this is blocking until you load the entire page and that degrades the overall, default experience of users.

Alice: So the proposal is stream but have some way of fallback.

2020-06-22

Minutes

Alice: The last sticking point was about streaming. We tried to ask for streaming being the default right away or not at all. Mason agreed that that will be a reasonable default and made arguments about being high implementation cost especially not seeing it used in practice. I'm somewhat sympathetic to this. Further, no other engines have indicated any interest in implementing it.

Peter: I'm willing to accept that. We can be happy with a design that says "it's impl choice" but at least the design should be "streaming by default" and hope impls can make that happen later.

Alice: Perhaps that wasn't captured well in prev comments. Can you add that comment?

Peter: Sure

2020-07-27

Minutes

Alice: It would be good to get Peter's thoughts on the do-not-stream="" attribute.

... I'd probably call it no-streaming

... when would you use the attribute?

Tess: Code will be written assuming the attribute is a no-op, because it is in the only known implementation.

Alice: Do we want to say the attribute must be provided if only a non-streaming implementation is available?

Tess: Would be better to say that without that attribute it's just a plain <template> that never gets instantiated, if there is no streaming and the no-streaming attribute is not provided.

... What would a browser that only supports streaming do when it encounters this marker?

... Other browsers will probably need to support non-streaming since there is this precedent, anyway.

Alice: I think we would prefer that shadowroot not have any effect on its own if streaming is not available, unless the do-not-stream/no-streaming attribute is present.

... Let's discuss this in the plenary with Peter

2020-10-12

Minutes

Ken: streaming not happening is basically the take-away.

Alice: strong pushback by webkit on streaming support...

reviewing whatwg issue

Alice: I think what is saying you can't ... [suggestion is] you either do streaming now or not at all.

Ken: process of insterting nodes is observable... revelaing the state of streaming.

Alice: that's him arguing it can't be optional. Because you can observe tghe timing of nodes beint attatched.

... then Mason says consensus to add later. then Ryosuke says no you can't...

Dan: do we need to adjuicate this dispute?

Alice: it looks like they are waiting for an update from Ryosuke.

... it seems like - i could comment saying "i read the linked issue.. it seems it's not clear to me that webkit is pushing back on streaming so much as implementation optional streaming support... " but I see why they have made the decision to punt it. So maybe we don't get streaming. Maybe that's OK. I'll make a comment.

Alice: I'll proposed close saying the main feedback we are having ...

2021-01-Kronos

Minutes

Alice: We had this as propose close - one outstanding issue Mason mentioned was the use of this feature as a potential sanitizer bypass.

Tess: Hm, that sounds like a real problem...

... mitigation also seems reasonable.

... I think we can close it.