We maintain custom element libraries at work, some using vue.js, some using svelte.js.
To be honest, this is not really a pleasant experience in either of framework.
While vue.js has tremendous issues with correctly outputting css for nested components, svelte technically works as expected, but the process to get there is very clunky and un-svelte-like.
Clunkiness in Svelte
To me, the biggest issue with building custom elements in svelte 4 is the <svelte:options/> api.
Since customElement must be a statically analyzable object literal, it cannot be dynamically generated using javascript.
This means that if you have to set a very large amount of properties, the config alone takes away a lot of valuable space.
<svelte:options customElement={{
tag: "my-foo",
props: {
// if not manually converted the attribute is: `mymultiwordprop`, which is bad dx at best and a trap at worst
myMultiwordProp: {
attribute: "my-multiword-prop"
},
obj: {
type: "Object"
},
num: {
type: "Number"
}
}
}} />
<script lang="ts">
export let myMultiwordProp: string;
export let obj: {a: string};
export let num: number;
</script>
for decent sized components, this can become so bad, that I ended up writing a vite plugin that injects the <svelte:options customElement/> config, just so that the amount of code inside the SFC stayed manageable.
Custom Elements in Svelte 5
svelte 5 already relieves part of this clunkiness, since props can now be declared as "attribute" kebab-case from the start:
However, most web components take props other than just strings, which in the case of a complex component still requires a lot of clunky configuration.
Describe the proposed solution
The Vue Approach
vue 3 leverages the information it gets from its defineProps() macro to automatically convert attributes from strings into the correct type. (vue does this only for basic types: String, Number, Boolean)
I've created two stackblitz reproductions, so you can compare what vue does differently here than svelte:
Proposal for Svelte 5: Implicit Conversion Leveraging Types
While svelte does not collect "type" information for non-typescript props like vue does, it should still be possible to make the process easier for typescript users (and with more and more users choosing typescript, that would be most users).
I know next to nothing about compilers, but I thought since svelte 5 now uses acorn-typescript for parsing the necessary type information might already be there, ready to be statically analized (assuming the script content is parsed)
While implicit type conversion would be a great first step, this idea could even be expanded to
use the $bindable() rune to show that an attribute should be reflected back to the host element
use an attribute on the style tag to signify that styles should be encapsuled into the shadow dom
I don't know if implementing this proposal is feasible, but it would remove a lot of the "boilerplate" associated with the <svelte:options customElement={{...}}/> clutter configuration of today.
Describe the problem
Motivation
We maintain custom element libraries at work, some using vue.js, some using svelte.js. To be honest, this is not really a pleasant experience in either of framework. While vue.js has tremendous issues with correctly outputting css for nested components, svelte technically works as expected, but the process to get there is very clunky and un-svelte-like.
Clunkiness in Svelte
To me, the biggest issue with building custom elements in svelte 4 is the
<svelte:options/>
api. SincecustomElement
must be a statically analyzable object literal, it cannot be dynamically generated using javascript. This means that if you have to set a very large amount of properties, the config alone takes away a lot of valuable space.for decent sized components, this can become so bad, that I ended up writing a vite plugin that injects the
<svelte:options customElement/>
config, just so that the amount of code inside the SFC stayed manageable.Custom Elements in Svelte 5
svelte 5 already relieves part of this clunkiness, since props can now be declared as "attribute" kebab-case from the start:
However, most web components take props other than just strings, which in the case of a complex component still requires a lot of clunky configuration.
Describe the proposed solution
The Vue Approach
vue 3 leverages the information it gets from its
defineProps()
macro to automatically convert attributes from strings into the correct type. (vue does this only for basic types: String, Number, Boolean)I've created two stackblitz reproductions, so you can compare what vue does differently here than svelte:
Proposal for Svelte 5: Implicit Conversion Leveraging Types
While svelte does not collect "type" information for non-typescript props like vue does, it should still be possible to make the process easier for typescript users (and with more and more users choosing typescript, that would be most users).
I know next to nothing about compilers, but I thought since svelte 5 now uses acorn-typescript for parsing the necessary type information might already be there, ready to be statically analized (assuming the script content is parsed)
While implicit type conversion would be a great first step, this idea could even be expanded to
$bindable()
rune to show that an attribute should be reflected back to the host elementI don't know if implementing this proposal is feasible, but it would remove a lot of the "boilerplate" associated with the
<svelte:options customElement={{...}}/>
clutter configuration of today.Importance
would make my life easier