lit / rfcs

RFCs for changes to Lit
BSD 3-Clause "New" or "Revised" License
15 stars 10 forks source link

[RRFC] Lazy loaded Lit elements #22

Open justinfagnani opened 1 year ago

justinfagnani commented 1 year ago

Motivation

Some developers would like to create a loader for a set of components that will automatically load element definitions as they are used. This is useful when you have a very large component set hosted on a CDN, so there's no specific module graph to load individual elements from, and you don't want to require your HTML-authoring users to write a script tag for every element they use.

It's a feature of Stencil, and Shoelace has built their own loader system.

Example

<head>
  <script type="module" src="https://my-element-cdn.com/my-element-collection-loader.js"></script>
</head>
<body>
  <my-element-1></my-element-1>
  <my-element-3></my-element-3>
</body>

In the case my-element-1, and my-element-3 would be loaded, but not my-element-2.

How

The basic approach is to register a stub element that loads the real definition when the first instance is created. The stub should contain static metadata needed for the definition like observed attributes, form association, etc.

We made an experiment for this a while back: https://github.com/PolymerLabs/split-element

Another approach would be to use a mutation observer, but that would only work in one HTML tree scope at a time. It would be fine for the main document.

Current Behavior

We have no lazy loading solution

Desired Behavior

References

basit-qayoom commented 1 year ago

Image 30-08-23 at 4 00 PM I was reading the stencil docs, script tag for distribution.. Can you tell me which file do i need to include in script tag

yorrd commented 1 year ago

I'm just here to say that I appreciate the direction this is indicating. We were thinking about building something like that ourselves, but an "official" solution would be much appreciated

maxpatiiuk commented 2 months ago

There is a also a custom-elements-manifest plugin that adds lazy loading as a build-step: https://github.com/break-stuff/cem-tools/tree/main/packages/lazy-loader


In house, we used an approach similar to Stencil, but improved, to create a lazy loading build output target for Lit elements.

The fact that lit-element and lit-html allow rendering to a shadow root of another component (via createRenderRoot overwrite in a custom LitElement base class), but still this-binding events to the current component has been very helpful for creating a pretty transparent proxy custom element.


Still, it's a bit sad that the web platform has no native easy solution for lazy-loading web components until one is added to the page (short of overwriting document.createElement and setting up MutationObserver). Combined with the fact that React 19 and Preact don't set props on the element unless they are present on the prototype makes lazy loading much trickier than it should be.