salesforce / lwc

⚡️ LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation
https://lwc.dev
Other
1.62k stars 394 forks source link

Make duplicate slots in light DOM behave like native shadow DOM slots, or disallow duplicates entirely #4497

Open nolanlawson opened 2 weeks ago

nolanlawson commented 2 weeks ago

Currently, if you use duplicate <slot>s in the same HTML template in light DOM, e.g.:

<!-- component.html -->
<template lwc:render-mode=light>
    A
    <slot></slot>
    B
    <slot></slot>
    C
</template>
<!-- app.html -->
<template lwc:render-mode=light>
    <x-counter>
        <div>yolo</div>
    </x-counter>
</template>

... then it will render the slots duplicated:

<x-counter>
  A
  <div>yolo</div>
  B
  <div>yolo</div>
  C
</x-counter>

This works regardless of named slots or the default slot.

This is in contrast with native shadow DOM, which renders the first slot but ignores any subsequent slots.

<x-counter>
  #shadow-root
    A
    <div>yolo</div>
    B
    C
</x-counter>

Either way, you will get a warning during template compilation:

LWC1137: Invalid duplicate slot (default).

This is because duplicate slots are generally a component author mistake. Usually you do not want duplicates – especially in native shadow DOM, where subsequent slots are ignored.

Here is a summary of how other frameworks handle this case:

So in other words, the current LWC light DOM behavior matches Svelte's and Vue's behavior.

nolanlawson commented 2 weeks ago

BTW this would be a breaking change and this issue is not up for grabs. I am documenting the existing behavior without proposing a solution.

It's also not clear that light DOM slots should behave exactly like native shadow DOM slots – there are plenty of cases where they don't (e.g. lazy vs eager rendering, support for scoped slots, etc.).

nolanlawson commented 2 weeks ago

Another option here is to turn the compiler warning into an error. This would make it much easier to reason about duplicate slots in either light DOM or shadow DOM, since they wouldn't exist. 🙂

However, this would be a breaking change, and so would need to be done via API versioning.