Re: [whatwg/dom] Declarative Shadow DOM (#831)

@emilio:
> What text should those stylesheets have? The serialized representation of their CSS rules? Or the original text that was passed to replace() / replaceSync()?
>
> Because for inline style you don't get serialized back the result of CSSOM mutations. It'd be weird if adoptedStyleSheets would do that.

I would say it should be the serialized representation of their CSS rules. Exactly akin to serializing the `#shadowroot` contents into `<template shadowroot>` declarative markup - in that case the content was imperatively created, but we still want to serialize it all as it exists fully-hydrated on the server. Yes, this is definitely a different mode of operation from normal `<style>` serialization. But perhaps this could be opt-in with the new serialization API?

By the way, I think this makes even more sense (subject to more bikeshedding):
```javascript
var html = element.getInnerHTML({includeShadowRoots: true,
   convertAdoptedStylesheetsToInlineStyles: true});
```
With a function API, we can add options more easily, and make it clear what should happen.


@justinfagnani:
> The ids in adopted-styles would probably have to search in the global scope, or possibly in ancestor scopes, not just in the scope they're defined in (which may be nested in other declarative shadow roots).

This is what I worry about with this proposal - no other web API has this type of cross-document reference structure, at least that I know of. See, e.g. [this thread](https://github.com/whatwg/html/issues/4925) and [this doc](https://gist.github.com/alice/174ae481dacdae9c934e3ecb2f752ccb) discussing options for how to reference one node from another. It seems that several rough conclusions have been reached: 1) cross-document references should be disallowed, and 2) an imperative API is preferred over an idref solution.

I'd really like to avoid tying this proposal for declarative Shadow DOM to an issue that doesn't (yet) have a good solution. Especially since, I think, an eventual style-ref proposal would still be backwards compatible with this declarative Shadow DOM proposal.


@adambradley:
> Concerns:
>
> * Is it safe to say the solution would not have a noticeable flicker between the time the declarative SD is painted and the component's constructor is called?

I suppose this depends on how the component is written, but I wouldn't expect any "flicker". In the [proposed example](https://github.com/whatwg/dom/issues/831#issuecomment-585372554), the component constructor just detects the pre-existence of the `#shadowroot` and doesn't blow away and re-create any content. So I'm not sure where the flicker would come from.

> * Will there be performance issues when there's a large list of items, and each item also includes a many child elements with shadow dom? When stress testing this scenario you can see some noticeable differences between a solution using adopted stylesheets, and one inlining style tags into each shadow root (especially on low-end mobile devices which Ionic is targeted for).

I totally agree that we need to stress-test this. Several other people (e.g. @dfabulich) mentioned the need for a "real world" example. I'm planning to build such an example and test out the performance, but if anyone would like to volunteer a candidate set of basic generic components and a real-worldy tree of those components, I'd be appreciative.

> * It'd be pretty easy for devs to explode the size of their html in comparison to traditional html/css. Maybe I'm overthinking it, but what's largely unknown right now is how shared styles could even be possible, but if not, does that also add to the problems that adopted stylesheets should be solving?

I agree that we need a solution for shared styles - I've proposed some basic approaches above. But my hope (perhaps naive) is that the two problems, declarative Shadow DOM and declarative adopedStylesheets, can be solved roughly independently.

> * Is it possible to avoid any additional JS checking the existence of a shadow root? Basically I'd like to avoid any new logic in the constructor if possible.

I'm open to suggestions for how to accomplish this - it would seem that at least a basic `!!this.shadowRoot` check will be needed. Perhaps `outerHTML` could be used to just blow away the entire node in the constructor? That doesn't seem especially efficient.

> * From what I can see, it seems a significant challenge is how styles are handled, especially around reusing styles. Curious if solving declarative adopted stylesheets should come first.

I agree that these are a challenge. I'm hoping we don't need to solve that first, or that some of the above suggestions might be workable. But maybe not.

> Overall I'm excited to see this discussion and absolutely can see how it'll benefit Ionic's use-case.

I'm really glad to hear that!


@rniwa:
> Could you get the new perf numbers after replacing template.content.cloneNode with template.content.importNode as well as just template.content? That would avoid adoption of the cloned nodes from the template's document into the destination document and cloning at all respectively. Otherwise, the most of runtime will be spent cloning & adopting nodes, not attaching a shadow root.

Ahh very good catch. I'm sorry I missed that. Yes, I'll remove cloneNode from the [baseline](https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#baseline---script-based-shadow-root-attachment) script-based element and re-run things. I'll check back here with the results when I've had a chance to run that.


@bzbarsky
> Attribute injection, which is what this is responding to, means injecting them on the parser level. So the fact that this is a parse-only feature is not a protection against attribute injection.
> Specifically, if a page has a `<template>` and you manage to get `<script>` inside it, right now that is safe. If you can also get this new attribute on the `<template>`, that is no longer safe...


I see - you're right. Attribute injection would allow the `shadowroot` attribute to get added to a `<template>` which would activate any child `<script>` elements. I'm not as familiar as I should be with the security aspects of this proposal. Can you elaborate on how one would *also* inject a `<script>` node inside the `<template>`? I.e. why is it more likely that this could happen inside `<template>` than outside? Otherwise, it seems easier to just skip the attribute injection and inject your `<script>` directly on the page somewhere, where it would run. Is it that existing sanitizers assume the insides of a `<template>` are safe?


@Rich-Harris:
> I think it's worth emphasising that custom elements cannot, in the general case, rely on the declarative shadow DOM a) existing and b) matching the component author's expectations. You might be able to rely on that situation if you're a framework that controls the components and the page, like Stencil, but not if (for example) you're writing a distributable widget.

Can you elaborate on this concern? It would seem that if my SSR framework is running the code on the server to generate the SSR'd content, and then shipping that same code off to the client to run locally, the shadow content would always match (modulo bugs). I'm sure I'm missing something - what is it?

> I think this is an essential point. Ideally, a new feature like this would grant new capabilities to web developers at large. I hope that feedback like mine — that this proposal wouldn't provide a reason to start using web components — is received as being constructive, as is my intent.

This is absolutely how I'm receiving your (and everyone else's) feedback. This has been a very helpful discussion.

@georges-gomes:
> But I'm concern about the `<template>` use. Is that used for technical reason or is it really idiomatically correct? `<template>` tag are not visible and here you want them to be visible.

I would honestly prefer a new `<shadowroot>` tag myself. But I don't know how to get around the very real [backwards compatibility problem](https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#syntax-template-shadowrootopen-vs-shadowroot). Before all browsers support this new feature, it is even worse than your concern about `<template>` being inert. The new `<shadowroot>` will be *completely live on the owning page* for browsers that don't understand that this new tag should represent an encapsulated shadow root. I'm open to suggestions here.

@UpperCod:
> I like more the idea of declaring the fragment attribute on the template tag, with the aim of associating a persistent fragment to the <host> node and being indifferent to the use of shadowDom for native SSR declarations

I hadn't seen [that proposal](https://github.com/whatwg/dom/issues/736) - I'll take a look. In general, though, I'm trying to avoid gating this proposal on other in-progress APIs. I really want to make declarative Shadow DOM a reality.



-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/831#issuecomment-586385698

Received on Friday, 14 February 2020 17:24:15 UTC