The WebC plugin brings a component model similar to frameworks like Vue and Svelte to Eleventy. It allows you to create HTML-only components (basically includes) all the way up to interactive Web Components with shadow DOM and all the benefits it offers.
I generally get by just fine without components in 11ty. Nunjucks macros are fine, but they never really felt like true components to me. They also are super clunky to work with, IMO.
Slots in WebC components do a bit more than the standard <slot> element used in Web Components. They have the ability to work just like Web Component/custom element slots, but they can also function similar to something like the built-in props.children in React.
I see a lot of potential here. You could do some very cool things when combined with layout chaining like create your own template/layout inheritance without having to use Nunjucks layout inheritance, or create compound components like a site header:
Render functions are pretty cool. To me, they seem a lot like shortcodes except you don’t have to register them in your .eleventy.js (or whatever yours is called) config file. Instead, you can keep them alongside your other components or includes as a HTML/.webc file. Here’s and example of a simple list component using a render function.
It usually takes me a while to really wrap my head around new concepts like this. I’m sure I’ll get there once I have the chance to work through some real-world use cases, but are some things that aren’t quite clicking for me yet.
I LOVE the idea of 11ty single file components, but it would rule to have some syntactic sugar for flow control similar to Vue, Svelte, etc. Also a mustache-like syntax for expressions that render data, variables, etc would be very handy. I could just be missing something here though.
Maybe a lot of folks are going to prefer what feels, in my opinion, more like JSX with render functions and the <script> tag plus webc:type="render" approach shown above. I dunno? The good news is that it looks like flow control features are being considered for the future.
In this example I’m trying to pass some front matter data from a template to a @heading prop on a component and render that data in the component. someData ends up passed as a string instead of being rendered as the value of the someData variable from the front matter. I’m almost sure I’m missing something here as it relates to @propName vs. dynamic attributes (ex. :attributeName).
--- layout: base.webc someData: "Eleventy front matter data" --- <!-- This DOES not work in a page-level template. The heading prop gets render as the string "someData". --> <list-component@heading="someData"></list-component>
The @heading prop is rendered as the string “someData” instead of the value of the front matter variable passed in as the @heading prop on the <list-component> element.
Maybe everything in the WebC component just needs to be a render function if you want to pass dynamic props in from external data sources? This may be super obvious to some folks, but I feel like I might be missing something here.
I guess you could go this route, but I’m going go ahead and say I’d rather wait and see on the potential enhancements to templating/flow control syntax mentioned above for now.
I need more experience to figure out the boundary between HTML only and a full-on Web Component (CustomElement + shadowDOM). As soon as you put a script or style tag in a .webc file it will render the custom element but you can use the webc:nokeep attribute you get rid of the custom element wrapper/parent.
On the other hand you can register full-on interactive and encapsulated Web Components (ex. CustomElements.define(...)) from single file WebC components, which is very cool. I think mixing interactive Web Components/CustomElements with render functions, slots, and HTML-only components has tons of potential to create a great workflow for building stuff.
There is so much potential here and I look forward to seeing how webC progresses over the next few months. I’m planning to try and keep this post updated as have more time to dig in and new WebC features roll out.