-
Notifications
You must be signed in to change notification settings - Fork 795
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
feat(ssr): shadow dom components can render as declarative-shadow-dom or as 'scoped' #6147
feat(ssr): shadow dom components can render as declarative-shadow-dom or as 'scoped' #6147
Conversation
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.
Some initial thoughts
Co-authored-by: Christian Bromann <[email protected]>
Co-authored-by: Christian Bromann <[email protected]>
Co-authored-by: Christian Bromann <[email protected]>
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.
Awesome work 👏 some minor nit picks, once pipeline passes I am happy to merge.
Co-authored-by: Christian Bromann <[email protected]>
Co-authored-by: Christian Bromann <[email protected]>
Co-authored-by: Christian Bromann <[email protected]>
@christian-bromann I had to un-deprecate |
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've been running some tests and discovered that the order of elements within the light DOM differs between DSD and scoped mode, e.g.:
import { renderToString } from './test/wdio/hydrate/index.mjs';
const { html } = await renderToString(
`
<ssr-shadow-cmp>
<p>Default slot content</p>
<p slot="client-only">Client-only slot content</p>
</ssr-shadow-cmp>
`,
{
fullDocument: false,
serializeShadowRoot: true,
constrainTimeouts: false,
prettyHTML: true,
},
);
console.log(1, html);
would return:
<ssr-shadow-cmp class="hydrated" s-id="1">
<template shadowrootmode="open">
<style>
:host {
display: block;
padding: 10px;
border: 2px solid #000;
background: yellow;
color: red;
}
</style>
<div c-id="1.0.0.0">
<slot name="top" c-id="1.1.1.0"></slot>
<slot c-id="1.2.1.1"></slot>
</div>
</template>
<!--r.1-->
<p>Default slot content</p>
<p slot="client-only">Client-only slot content</p>
</ssr-shadow-cmp>
But when setting serializeShadowRoot: 'scoped'
, I get:
<ssr-shadow-cmp class="sc-ssr-shadow-cmp-h hydrated" s-id="1">
<!--r.1-->
<!--o.0.2.-->
<!--o.0.4.-->
<p slot="client-only" hidden="" c-id="0.4">Client-only slot content</p>
<div class="sc-ssr-shadow-cmp sc-ssr-shadow-cmp-s" c-id="1.0.0.0">
<!--s.1.1.1.0.top-->
<!--s.1.2.1.1.-->
<p c-id="0.2" s-sn="">Default slot content</p>
</div>
</ssr-shadow-cmp>
Note: the order of the slots changing.
I think that makes sense @christian-bromann in 1, the shadow dom is separate from the light dom and the browser takes care of how it’s rendered. The in 2, there is no shadow dom so the dom gets resolved and rendered as it appears as a light dom tree. The |
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.
Thanks for clarifying, that makes total sense to me 👍
Before we release this, can we raise a PR for the docs with an update?
Yep - will do tomorrow |
What is the current behavior?
When generating a
shadow: true
component during SSR, Stencil renders a Declarative-Shadow-Dom (DSD).Generally, this is preferable as it's natively supported in most browsers.
There are some scenarios at present, where DSD is not ideal:
(* e.g. given
my-list-item
component which is rendered 20 times. DSD will render 20<style>
tags which can negatively impact the initial weight of the page - especially without compression.)GitHub Issue Number: N/A
What is the new behavior?
The ability to use Stencil's
scoped
behaviour has been extended for use during SSR.During SSR a
shadow: true
scoped component will be rendered without atemplate
- just plain, lightDOM html and a single<style />
tag added to the<head />
.On the client, these lightDOM nodes get added to a new shadow-root and the
<style />
tag is added as a `constructible stylesheet'.To this end, the
serializeShadowRoot
options (passed intorenderToString()
) now accepts a number of new options:'declarative-shadow-dom'
- will render allshadow: true
components as DSD'scoped'
- will render allshadow: true
components with Stencil's scoped behaviour{ 'declarative-shadow-dom': ['tag-1'], default: 'scoped'; }
will render component tagstag-1
with DSD, but all others with Stencil's scoped behaviour{ 'scoped': ['tag-1'], default: 'declarative-shadow-dom'; }
will render component tagstag-1
with Stencil's scoped behaviour, but all others with DSDfalse
- will disable all SSR render behaviour forshadow: true
componentstrue
- DEPRECATED will render allshadow: true
components as DSDDocumentation
stenciljs/site#1507
Does this introduce a breaking change?
Testing
Other information