WebC: Prerelease, Promise, and Pitfalls by Benny Powers | 11ty Meetup
So today I want to talk a little bit about my experience working with WebC. When I first heard about it, I was really excited and I was sort of looking for excuses to try it out. And I have tried it out and I have some thoughts that I'd like to share with you. Some thoughts and opinions. So let's dive in. So about me basically I've been working with web components since like the Polymer 1.
1, 1. 2 era back with HTML imports, you know, and I really enjoyed web components from the beginning and I've basically staked my career on web components and HTML and, and standards aligned development. To that end, I've been advocating for the use of web components in all kinds of different contexts.
I wrote a fairly popular blog series called Let's Build Web Components, which sort of goes over the basics, the standards, some of the libraries, some of the common misconceptions. I've also published a number of web components related libraries on GitHub. So one is Apollo Elements, which is sort of like GraphQL.
Client side web components. Another one is Stripe elements, where you could actually, they, I think they recently published their own custom elements, which is amazing. But for the longest time, if you wanted to use Stripe payment processor with shadow roots, so probably the best way would be to use that library. And my day job is making design systems with you guessed it web components at Red Hat. So in that time, I've also been sort of turned on to Eleventy. It probably doesn't surprise anyone here that someone who is interested in web components and standards aligned development also eventually figured out how cool Eleventy is.
So for example, the website that you're looking at right now, my personal blog, it's made with Eleventy. We use Eleventy and I advocate for it personally at work. In addition to that, I contributed to a framework called Rocket, which is like a static site generator, similar to Eleventy when it was in pre release and back in its pre release days, it was actually a subclass of Eleventy. Interesting. Since then it's moved on and it's sort of become its own thing. But at the time I got to sort of peek in behind the scenes and get to take a look at the a little bit of the innards.
I've also published two libraries on GitHub. A slide decks plugin, which you are enjoying right now, and neovim editor plugin for WebC, which adds syntax highlighting and maybe a couple other niceties and hopefully some more features features in the future as well. So how do we use Eleventy at work? Well, first of all, my team, we're responsible for design systems at Red Hat, and so our sort of, our home base is ux.redhat.Com, and that website is built with Eleventy.
It was actually rocking Eleventy before I joined the team, so it was very cool to go in there and say like, oh, hey, look, there's like an Eleventy configure. Fantastic. So felt right at home. In addition, we have sort of like an up it's red hat.
So of course there's like the downstream corporate design system. And then there's like the up upstream design system. So that website also pattern play elements is made using Eleventy.
So both of those are sort of doc sites for design systems, which include things like API docs on our custom elements. How do you use our alert? How do you use our card? That kind of thing. It includes live code playgrounds, courtesy of Google's fantastic playground IDE custom element. So it's sort of like CodePen, you know, in a web, in a web component.
And we also have our own sort of like chibi storybook kind of demo collator that puts demos on the website. All of that is courtesy of our Eleventy config. So why do we like Eleventy at Red Hat? Well, I've already mentioned the standards aligned development thing. And I love that phrase standards aligned development. I, I don't want to misquote, but I feel like I maybe heard it from Jared White first, but correct me if I'm wrong. The idea that like, we're trying our best to just use what the browser gives us, and if we're using build tools or libraries or frameworks, at least we're choosing tools and libraries and frameworks, which are have have platform aspirations that want to get into the browser or want to, you know, just disappearing framework.
So that's kind of the idea. The thing we like about that is that it builds and preserves preserves team skills. So, like, the people on our team learn web components, and then they've learned more about html. And that makes them better web developers instead of making them better. Framework of the month developers.
We also like how portable Eleventy is so we can run it on any build environment, including my laptop, and then just ship those, those files to any web host and we're done. If we don't like the web host that we're using, we can move on to another one. So we, we value that a lot. We also adopted a deploy preview workflow, which is not exactly an Eleventy feature, but Eleventy really lends itself to that kind of a thing. Because of the, because the static website generator that's really drastically improved our review workflow. So designers can come in and check the colors on a button and say like, okay, this is good, move on.
So learning web components teaches you HTML. They're portable. You can move them into any framework, you can run them on any backend. We like that sort of save and reload workflow, or you don't need like a huge, you know, you don't need to hire a web pack engineer in order to get your project. I've been running, you can just save the page and reload the browser and Hey, there it goes drastically reduces the tooling burden and web components. Give us those good old HTML vibes.
Like there's nothing I like better in polymer one than just like looking on the side of my editor and seeing all these HTML files lined up. It was great. Really hope we can get back there soon. And especially, you know, at a company, a large company like red hat, where.
Not everyone who's making web stuff wants to install Node. js on their computer wants to use the NPM ecosystem and having been in this joint full time for five years, I get it, you know, I understand that. So we we like to give them options.
So. You know, when, when I was initially drawn into web components, it was sort of that good old HTML thing. A lot along the way, somewhere around Polymer 3, I feel like the messaging kind of shifted more from, from an emphasis on HTML towards an emphasis on framework interoperability. But maybe that was a strategic mistake. It could be, I don't know, you know, hindsight is 2020.
I feel like maybe we haven't like gotten the audience that we wanted from that, from that decision. But that sort of led me to develop this Apollo Elements library, which has support for a number of different frameworks. And it also, you can write your web components with a number of different libraries.
So having that experience and then reading, you know, seeing David East talk about Nunjucks short codes being the same as components. Like I sort of immediately was shaking my head, like, Oh yeah. Like I've been there, like looking at, you know, my, my sort of like nunch uxy Eleventy website and thinking like, well, you know, this short code is basically just a server side web component and it's definition lives in my Eleventy config and seeing him say that I was like, Oh yeah, that makes a lot of sense.
Right. So when we first heard about WebC, it was like. Slam dunk, right? It's a component framework for Eleventy. Standards aligned development. You know, Zach Leatherman.
He's like the Chuck Norris of standard, of static site generators. You know, insert dad joke here. Et cetera, et cetera. So what's not to like, right? It was it was really exciting. And we were, we were excited to try it out. So let's talk in this talk, basically, I'm going to talk about our impressions of working with WebC from the perspective, mostly, of design systems and web components engineers who have a strong standards aligned development ethos.
So that's sort of where this, this talk is coming from. So let's start with the good stuff. So WebC is super fresh. It's got a really low barrier to entry.
Especially if you're starting off like a brand new project, you know, starting from day one the immediate familiarity of WebC to anyone who's worked with HTML and CSS before it's, it's really refreshing and it really lets you get up and running and iterate very quickly. We did an internal experiment to evaluate what it would be like to migrate one of our CMS websites over to Eleventy with WebC and we found that the designers and the technical writers who were responsible for the content on the website were able to really quickly pick WebC up after just a couple of short training sessions and they were off and building websites. So they were identifying repeating patterns, abstracting them into components, applying those back. Onto the pages, integrating our custom elements design system is amazing. It was very cool.
There was a lot less of this sort of specialized syntax and jargon for them to learn and pick up and start to, you know, try and break their teeth over. And the process of learning WebC gives you this progressive learning path. You can build on your existing HTML knowledge, which you already came in with. And WebC itself also works very similarly to HTML.
But sort of the thesis of this talk is that it isn't actually HTML. So that's sort of what we're going to get into in the next part of the talk. So it's important to remember that WebC is pre release software, right? And, you know, when I say pre release and when I look at that version number zero. 11. 4, which is the current version number.
So let's just sort of align on our definitions here. So when I see that zero in front, what that tells me is that breaking changes are allowed, you know, you can expect breaking changes to occur over here don't treat this like you would sort of a stable kind of. I don't know if production ready is the right terminology to use.
It's just like, if you're going to adopt this and if you're going to use it, just be prepared for for changes to come down the pipe. And so that's what that zero in front signifies to me. And the semantic versioning specification specifies that if you put a zero in front, so that kind of bumps everything down. So normally the first column is your major breaking changes. The second column is additive features. And the third column is non breaking fixes.
So in the case of a pre release with the zero in the front, so now breaking changes shift over to the second column and then additive features and fixes break over to the, to the third column. So bearing in mind that Eleventy is pre release software, it is now time for. The airing of the grievances, right? It's, it's actually holiday season here in Israel. So I literally just pushed like the last few typo fixes to this presentation, like five minutes before the presentation. So everybody, and thank you for having me. So before we get into sort of the into the weeds, it's important to put any critique here into its proper perspective especially considering where we're coming from in our use case.
So, like, our use case is fairly specific, right? And our interests are also very, you know, pretty well developed. And it's also important to understand where the critique is coming from. Like we're here, I'm here, my team is here because we, we love Eleventy and we think WebC is really cool.
So that's why we want to talk about it. So, you know, nowadays on the internet, it's hard to say a thing without it ending up sounding like something else. So I'm, this isn't about like WebC bad or anything like that. So I don't, you know, if you get that impression, remove it and just think about Festivus, get in the holiday mood.
Okay. So some of the less than fresh things that we've noticed about WebC is that WebC is not the same thing as Web Components. So for someone who is working with Web Components on a daily basis, there's a lot of overlap in terms of sort of the syntax, and there's overlap in terms of maybe the workflow and some of the concepts. Really, at the end of the day, it's not exactly the same thing, and I'll elaborate on that shortly.
In particular, WebC's slot component is a very different beast from the html slot element. They work in different ways. They have different effects on your code and on your website. And it's important to know the differences and the limitations of both in order to succeed at building a website with. with WebC.
WebC's scoping feature is not the same as the browser native scoping feature, which is called shadow DOM. And we've also noticed certain cases where the sort of the data management, which usually in Eleventy is like chef kiss. There are certain cases where it can be a little bit awkward and But maybe we'll get into that a little bit later on in the talk. So before we go into sort of the nitty gritty differences between Web Components and WebC, it's important to define our terms.
So what actually is a Web Component? When we say Web Component, what do we mean? So Web Components are a way to make your own HTML tags, right? So just like your browser came with a a details summary, Tag. It came with a figure fig caption tag. It came with a table tag. With web components, you can make your own tag. You can do like fancy button or you can do like my avatar, that kind of thing. And there are, there are lots of different things that you can use to make web components, but basically you need at least one of the two following things, which is custom elements or shadow DOM.
It used to. It used to require calling the attach shadow method on on an element. Nowadays we have this thing called declarative shadow DOM, which is available on, on Chromium and WebKit, and it is soon going to be available on Mozilla. TPAC was last week, and Mozilla has publicly said that they are working on it, and they hope to ship it soon, which is Amazing.
Next slide. So the slot element, it's a feature of shadow DOM, which allows you to project content from The light DOM into the shadow DOM. What I mean by light DOM is just like the regular, regular HTML.
That's, you know, web component. People call that light DOM. And then the shadow DOM is sort of this like private area that just belongs to your element. But you can put a slot element inside your shadow DOM and say, Hey, I want all of the children of my web component to show up here in this part of my template. So like, let's say you had a card element. You could say, well, this has a header slot.
A body slot and a footer slot. And then your users could say, you know, my card, H3 slot, header, blah, blah, blah, a paragraph of text, and then, you know, my button slot footer. And that would go into, those would all project into the right places into the shadow DOM.
But crucially those elements would stay where they are on the page, right? They wouldn't be removed as children of your element. They would just appear to be in those places, in those slots. Where the author of the web component specified. Why is it important that they stay where they are? First of all, so that you can target them with global CSS or with light DOM CSS. Right? So if you want all of your links to be a certain color, you can still do that, even though they're showing up inside your, they're appearing to be inside of your web component somewhere.
And as well, there are other APIs like assigned element that you can call on the slot element and things like that. The long and the short of it is the slot element works in a certain way by projecting content. WebC's slot component, and I'm using the word component here. Particularly because when WebC's compiler, like sort of virtual DOM compiler sees the slot tag, it goes into a whole separate process than it would just a regular div, right, kicks into its own WebC framework thing.
And the main thing that it will do is it will actually move that content from one place into another. So if I have a slot inside of my WebC component, instead of having that content projected by the browser on the user's screen into that place, instead of what I'll have is the server moving that content from one place in my source file to another place in my output file. And that's a crucial distinction because in the shadow root you can use things like the slotted pseudo selector in order to target slotted elements. You can do things like set up name slots and target them both from inside the shadow DOM and from outside the shadow DOM using CSS. And you can also, like we said, you can apply your global or light DOM styles to your Light DOM children, that's, that's just the way that slots work. But the way that Eleventy handles this can lead to some unintended consequences.
So here's one I prepared earlier. Let's go over to the next. Okay you can see the GitHub page.
Okay, so this is actually the, the WebC file for this presentation. And while it, while I was writing it so it being holiday season, I have, I have actually haven't touched WebC. project in like a month or two. So I had forgotten already all of the workarounds that I had to do to deal with slot.
And I got to rediscover them all while I was writing this this presentation. Right. So here's an example of one that came up, right? So this slide deck element is a WebC component that wraps a custom element. The WebC component has a WebC slot and the custom element has an HTML slot. Confused yet? I was. Now, if I want, normally the way the, the slide deck plugin works is you have to write all your content in Markdown files and it will make a collection in Eleventy and then sort of schlep those into your, into your slide deck.
I didn't want to do that. I wanted to make the whole presentation in one big file. So I decided to add a slot to the WebC. Slide deck element, a WebC slot, a transclusion slot.
But that didn't really work. When I first tried it, like I would have expected to just like put my slides in there and have them show up. It didn't go, I'm not sure. I don't really know why it didn't go, but I found out. That if I do one, no, keep template, tell it to go into that slot and give that slot a name. Okay.
Then work. Fine. Another couple of places where I ended up dealing with this is that some of my slides have presenter notes and normally what you would do if this was all just web components running on the, on the browser you could just put your content, assign it to the slot that you wanted to go into and. You'd be off to the races.
I couldn't do that here though, because this slot attribute, as written in my WebC source file, that slot attribute means WebC slot facility. Like when the WebC compiler gets to that slot attribute, it'll say, Oh, I know what to do with this. I know to do WebC stuff right now, but I, the author, what I wanted to happen was I wanted it to print HTML and then have the browser project that content into the notes slot. Well, that didn't happen and ended up with slides that didn't have any notes cause there's no notes slot in the WebC component.
Confused yet? I was, right? The solution again was to wrap all of that in a raw, no keep WebC template. This was a kind of a jarring experience and not one that I would want to recommend to sort of like a, like a newcomer on my team or someone who wasn't as familiar with these, with these technologies. So let's go back to the other to go back. There we go. Great.
Okay. Are we back to the presentation? Great. Thank you very much. So because of all this, we have like a couple of suggestions that we would like to humbly offer to the WebCE community. So one, We, we feel it would be best to disambiguate these two technologies, right? Like the browser slot is one thing. It works in a certain way.
It has its own semantics. It has its own meaning and its own APIs and its own functionality. We feel it would be best if the WebC slot was explicitly different. Something that was clear and obvious when you were using it, that it's not that slot thing.
So how would that end up looking at? Well, I don't know. Here's a couple ideas how it might end up looking. Maybe there'd be like a special namespace on the tag name. Maybe it would be, it would look like a custom element name with the, with the dash in between.
Maybe there would be special attributes that instead of having to opt out of framework behavior, you would have to opt into framework behavior. And without those attributes, you would get the native browser behavior. I don't know which of these is better. I don't know if any of them are particularly good.
My sense is that probably it's better to go with the colon because that's sort of like quote unquote illegal HTML. So it'd make a very clear distinction between the browser feature and the framework feature. But, you know, season to taste. So there's, there's more to say about this, especially when it comes to declarative shadow DOM when, when making, or I should say when trying to make.
Web components, proper web components, you know, quote unquote web components using declarative shadow DOM via the WebC framework. You can get into like infinite loops where it doesn't know where it's trying to project its own content back into its own slot and again, and again, and again, and again. You can get into situate. There are certain things that you just, you simply can't do. Like you can't thread content through a WebC component down into a native slot under certain circumstances that can be very confusing spent hours trying to solve some of these problems. Well, if I put an intent, if I wrap it in a template, if I use a, if I escape to a script template and put in like.
SL plus OT. None of it ended up working. Very frustrating scenario. But I don't want to go into the details there. Just, just know that it's it's not particularly pleasant and doesn't always work. Okay.
So that, that was sort of the main issue that we had with working with WebC is that as web components developers, we wanted to use slots and it was, it was just not ergonomic. It just wasn't going for us. Another one of the kind of head scratching moments we kind of had as again, this is coming from people who are working with web components all the time was the scoping facility in WebC. So there's this like WebC scoped attribute, which will basically kick this bundling CSS bundling process.
into action and it will assign sort of randomized class names and it kind of, kind of works like the old Shadow DOM polyfill that the Polymer developers used to ship to the client side where it would put on class names and sort of scope in that way. And it's actually pretty nifty feature. If you're living in sort of like a global CSS kind of I guess maybe more like traditional web development world, but for people who are used to writing encapsulated shadow CSS going like my coworker, Steven, who's here on the call. Hi, Steven. Like he said, just going back to global styles to do component stuff was, it was sort of a disconnect, you know and you'd have to sort of context switch between like, oh, okay, now I'm writing WebC stuff. And I have to think globally.
Now I'm writing. And I get to think locally, so that was something that we noticed when working with the style scoping. We also had some kind of you know, kind of balancing on our chairs moments dealing with some of the data binding facility at WebC. Generally speaking we've found WebC's data binding facilities and syntax to be really nice to work with.
Just like extraordinarily pleasant And I think most of that comes with it's sort of, it's like HTML, it's standards aligned. If you get HTML, you can bolt a couple things on top of your knowledge and get, you know, a templating language. So those, those were great, but on a practical level in an Eleventy site, and I'm sure the people on the call have experienced this as well, sort of like the difference between dollar data. Global scope data, what happens if it's in components, if it's an include, you have to remember where the component came from in order to know how to do it. It's, it was it was odd to say the least. As well, there are certain things that you just can't do right now with Eleventy's current data binding syntax.
So like oftentimes you might have an expensive operation that you want to run, get some data and then assign that to a name so that you can use it several times in your template. Like go and get my list of users with the, with the API token. And then here's the list of users.
How that works or maybe do Jared White suggesting wrote a block blog post about this recently was to write a helper function, which is a great suggestion. But, but that having a helper function doesn't help with the naming problem, right? So it'd be very, it would be nifty if you could say, like, have. Say like you have a UL element or an article or something like that, and you could scope a piece of data to that article, and that name, that prop, would be available in that DOM tree, that you could just reuse that prop down below. One workaround for that is you can make a new component. And just, you know, send the prop into that component and extract that little DOM tree out into its own component, do the calculations over there.
That's pretty cool. But you don't always want to have a separate file for that, you know what I mean? Just to show, you know, a list or something like that. Sometimes you just want your whole template to be in one file. But again, this is not to be over emphasized. We've generally found the data mining facilities to be very nice to work with. So a couple open questions and ideas that we've had from our experience using WebC.
HTML slots, not, not WebC slots. So with some of the I don't think like competing or rival libraries is really the right term. It's sort of like the sister libraries, like with the lit framework ecosystem, they have an SSR module that you can use to run those processes on the server.
What would that look like in a future version of Eleventy? We have some questions around sort of like enterprise, I get to say enterprise scale. Ah, like I'm some kind of a, right? Like enterprise scale, haha, translations. Like what would that look like working in concert with a CMS or like like an API or maybe just a big blob of JSON? We'd be curious to hear your experiences with that. And we also have some thoughts about maybe working with existing custom elements.
There's a file format called Custom Elements Manifest, which is like a big JSON that has all of the APIs on a custom element in it. So if you have this attribute or this CSS custom property, this slot name, this event, the manifest says, like, here's this, this is what it's for, et So could we take one of those and then code gen up some WebC components? One thing that we've one, one process that we found really interesting is like, say you have a very flexible custom element that can be used in multiple different ways. So maybe you'd want to whip up a WebC wrapper for that custom element. That generates it's complicated light DOM. So an example would be like a table component or a nav custom element, you know, big, big mega menu nav thing that has a ton of, of light DOM content.
Whip up a WebC that takes data and prints the light DOM into that custom element, very cool workflow. So a couple of takeaways from our use of WebC should you adopt Eleventy in your projects? Yes. Go ahead. Eleventy is great. We think Eleventy has got everything you need.
Should you adopt WebC right now? Maybe. It's not the kind of thing that I would jump into immediately if there were, if there were like big bucks lying on the line or like whole teams being blocked by that work, mostly because of the pre release part and also because of some of the issues that I've, that I've brought up previously. If you're not using Web Components and can guarantee that you won't be using any Web Components, Like for example, material web, you're not going to be using that. You're not going to be using Google maps. You're not going to be using any of the other, you know, every day, there's more and more web components libraries that come out. So you can guarantee you're not going to be using that and you can avoid those questions.
Go ahead. Or alternately, if you're ready to employ the workarounds that you'll have to do when dealing with slots and ShatterDOM and that kind of thing, go for it. Or if you're just looking to flail about and find out. Then I think you will enjoy yourself and I think you will you'll learn a lot and I think you'll be able to contribute to the community as well.
With lots of nested DOM and things like that. So WebC is. Perfect companion to that to lay out that internal DOM for you instead of having to lay that burden upon the developer You know developers just let's just like just give me a prop and i'll give you my data You know webc is great for that. And so for someone who's maybe unfamiliar or doesn't really use the real web components And maybe wants to componentize a site that they're building on their server and they'd also don't want to invest in like a react matter framework, you know? So it's a, it's a great case for that. As my colleague, Steven pointed out, thank you for listening to my spiel again.
I know there's a lot of critique here. I just wanted to frame again, where this critique is coming from. Like we're here taking our time out because we appreciate this project and we want to see it grow and be adopted more and have more features built in.
So thank you for listening and I'm very happy to take any questions.