-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
First off, thanks for creating and maintaining Svelte! It is a fantastic framework. 🙂
Summary
TL;DR: I would like an option like
{ styleEncapsulation: false }
... which does the same thing as customElement: true
without actually building a custom element. I.e., it would remove the svelte-*
classes from the DOM rendering and CSS, but do nothing else.
Justification
Currently there are several issues with using Svelte in customElement: true
mode, such as:
- Lack of an implicit
$destroy()
call can cause memory leaks: ondestroy in custom elements #1152 - Props are not set at creation time, requiring timing workarounds Prop initialization in web/standalone components #2227 (comment)
- Supporting reflected attributes with kebab-case is tricky Allow hyphenated properties to be defined in a component #3852 (comment)
- Every component-within-a-component gets its own custom element, which is not always what you want (e.g. a standalone web component built with Svelte)
- The constructor is not to everyone's taste (e.g. I prefer to pass the props in directly, rather than
{ target: ..., props: ...}
).
Also: the solutions are not obvious. For instance, I would prefer to create the Svelte component in connectedCallback()
and destroy it in disconnectedCallback()
, but perhaps others have different needs. You could also imagine folks disagreeing on whether to use shadow DOM or light DOM (#1748), closed shadow versus open shadow, or even the emerging declarative shadow DOM standard.
Proposal
So here's my pitch: instead of a one-size-fits-all solution for custom elements, what if we separate the concept of style encapsulation and custom elements? Then users could just use the standard Svelte component API to create their own web components. It doesn't actually require much code, as I found through tinkering.
However, this approach isn't really viable because of how CSS is handled. There's no way to create a regular Svelte component without the built-in style encapsulation, i.e. without the svelte-*
classes. You could write a Rollup plugin to remove the svelte-*
stuff and attach the CSS to shadowRoot
instead of document.head
, but that gets kinda gnarly. (Or you could just learn to live with the extra unneeded svelte-*
stuff, but I'm a perf guy, so I'm against that. 😁)
To be fair, with my proposal, the solution for "components within components" would just be that it's up to the author to make sure that styles are properly encapsulated between the inner and outer components. But I'd argue that this is probably the default case, especially when you're building a standalone web component for third-party consumption.
So this is my proposal. I hope it's interesting at least! 🙂