Skip to main content
595

March 31st, 2023 × #web-components#lit#interoperability

Supper Club × Web Components and Lit with Justin Fagnani of Google

Discussion with Justin Fagnani of Google about web components, how they work, the intent behind their creation, and how libraries like Lit integrate with them.

or
Topic 0 00:00

Transcript

Announcer

I sure hope you're hungry.

Announcer

Hoo. I'm starving.

Announcer

Wash those hands, pull up a chair, and secure that feed bag, because it's time to listen to Scott Tolinski and Wes Bos attempt to use human language to converse with and pick the brains of other developers. I thought there was gonna be food, so buckle up and grab that old handle because this ride is going to get wild.

Announcer

This is the Syntax Supper Club.

Guest 1

Welcome to Syntax, the podcast with the tastiest web development truth out there. Today, we've got A long awaited show. We've been trying and thinking about doing a show on web components and lit for a long time. We've talked about it here and there.

Topic 1 00:52

Introduction of Justin Fagnani

Guest 1

And today, we have Justin Fagnani

Guest 2

on hopefully, I I said that okay. You got that exactly right. Awesome. Well, thanks so much for coming on. Really appreciate it. Thanks for having me. I've been wanting to come on here for a while too, so this is great.

Guest 1

Let's talk about one of our sponsors. That is Sentry. They have a Brand new integration with actually a company that just joined them. It's called Codecov. It's a code coverage tool. And what that means, if you've never heard of code coverage before, It will look at your tests and it'll look at your code base and say, all right, well, your tests are covering this many lines of your code base. So there's there's a possibility that there's code In your codebase, that is not totally covered.

Guest 1

And that's super cool. It's easy setup if you're ready, a Codecov and a Sentry user on GitHub, the integration is enabled automatically for you. You can see your code coverage directly in your stack trace so you can see untested, partially or fully covered Code that may be causing errors, and you can fix your test to avoid any similar errors that pop up.

Guest 1

It's free to get started, but they're Also offering a promo pricing where if you have a Sentry team or business plan, you get the first 5 Pro Codecov Seats for $29 a month or a $40 savings. So you're going to want to check that out.

Guest 1

If you haven't signed up for Century already, go to century.

Guest 1

Oh, and use a coupon code Tasty Treat. That'll give you 3 months for free. Thank you, Century, for sponsoring.

Guest 1

So I told you, I'd start off with a bit of a hot Potato question just to fuck the listeners here. So, we'll start with the hot question, then we'll sort of go back and and talk about it because I don't like the controversial stuff too much. But, why do people use React when we have a standard

Topic 2 02:33

Discussion on popularity of React vs web components

Guest 2

like web components and awesome libraries like Lit for writing those components? I mean, there's lots of reasons to use lots of things. I say, like, I'm gonna give you the the non hot, like, political answer here, but it's true. I mean, React, React is insanely popular. I think for a lot of people, they have to have, an exceptional reason to not use it. Right? Everybody they know uses it. Their work uses it. That kind of stuff. Yeah. In terms of, you know, people who have use cases that fit into, like, web component strengths and maybe don't know it. Like, you know, they should check it out. Like, especially people vending, reusable components out there. Right? Like, the people who used to write, little jQuery plug ins and wrappers, and, like, here, make a chessboard on my site. Yeah.

Guest 2

Those people who are still using React, I definitely think they should move to web components so they can target you and Angular and everyone else, in the world. Yeah. Honestly, I think that's where Scott and I have been for so long is Why are we making,

Guest 1

React Grid and a React video player? And then all of a sudden, okay, now we need to make it for other things. And then we're starting to see, like, companies like, Mux, who has a player, and instead of making a React version and whatever, they make a web component version, and you can use it with With all of the ones. So Scott and I have sort of been coming around to the whole web components thing, and I think you could probably hear that over the years. So,

Guest 2

excited to ask you all the the questions I have. But, anyways, why don't you introduce yourself? Who are you? What do you do? All that good stuff. Yeah. So my name is Justin Fagnani, and, let's see. I've been at Google for a long time now. But for the last, 6 or 7 years here, I've been working on web components and, Related specs and then library style. You build them initially polymer, and now lit.

Guest 2

Yes. So my passion has been, you know, developer productivity and developer tooling for a long time. I started this project called App Maker at Google, which is like a low code environment, and then I had a little diversion to work on Dart for a while, trying to help people around JavaScript issues, and then, yeah, came around to web components as,

Guest 3

You know, somewhere I wanted to put put my effort and make the web better on. Nice. Those are all things that I have used. Use your step maker. Yeah. I've I've definitely tweaked it. Yeah. There's dozens of us. Yeah. No. I I'm I'm a sucker for for that type of of thing in general. So, like, if anything comes on my radar, I wanna try it, even if it's just for 5 minutes. Cool. But so okay. Do you wanna give the audience a 101 on on web components? What are web components for the, uninformed?

Guest 2

Yeah. The easiest way to think about web components is, you know, what if the browser vendors weren't the only ones who could make their own HTML elements? Right.

Topic 3 05:03

Explanation of what web components are

Guest 2

Another way of putting it is that the browser already has a component model. That's the HTML elements that are in there. So divs and inputs and video tags, iframes, all that, Those are components. They're written to interfaces inside the browsers and interfaces that users use, via the Dom APIs.

Guest 2

And web components opens that up to all developers and says you can make your own elements, and you can use the component model that the browser already has. You don't have to, kind of buy into a over the top user land component model. Cool. Yeah. And they generally there's 2 main, specs that people talk about with custom elements, I mean, with web components. There's custom elements, which lets you define your own tag, and then there's Shadow DOM, which lets you put the internals of that

Guest 1

Tag into a special area of the DOM, a private DOM area. Oh, so those those are 2 separate things. I actually did not know that. That's why I'm excited to have you on. So the Can you explain what the shadow dom is?

Guest 2

Yeah. So a shadow dom is basically a document fragment.

Guest 2

It's a little piece of it's a subtree, you might call it, of the DOM, that's hanging off of the element. And this is a place where the element can render its internal DOM. So the structure that actually builds up the element separate from the main document. In that way, a code that's looking at that element from the outside, code that's using that element. It doesn't see the internals.

Guest 2

It can't accidentally mess them up, modify them. That's, query selectors aren't gonna go in there. It's it's encapsulated, and it's private. And so there's a couple of benefits you get here. You get style scoping.

Guest 2

Styles for that element only apply inside that shadow DOM so that you're not gonna style every paragraph in a page.

Guest 2

You get the DOM scoping for, like, query selector.

Guest 2

And then maybe the biggest feature that you get that people don't talk about much is, interoperable composition.

Guest 2

So if you're using a framework and it puts, Yeah. The framework becomes responsible for putting both the internal DOM and the components' children into the DOM at the correct locations.

Guest 2

So this would be like React children or view slots or stuff like that. The platform does this for you with Shadow DOM. If you put a slot element inside of it, the children of the element will be rendered where that slot is. And that lets you have kinda children

Guest 1

that work regardless of what framework you're using. Right? Like, you don't have to buy into the framework of the element in order to stick children in the right spot. Like, a a very simple example, maybe you could correct me if I'm wrong, is that the HTML 5 video tag has a shadow dom. Right? Like, if you were to at least in the past when I've inspected The HTML 5 video tag, when you open up an MP 4 directly in the browser, you can see that the play button is like a span or a button and and all that stuff. But when you when you embed a video into your page,

Guest 2

it's just a video element, and your your selectors aren't actually gonna go into the video. Is that that's right. Right? Yes. Yes. That's true. I think I think it's true for most browsers. It's not required that they implement things with the Shadow DOM, But I actually think the browser's internal Shadow DOM predated the external DOM API that we call Shadow DOM now. So that they already have this concept of encapsulated, DOM areas.

Guest 3

Do you know if it was called Shadow DOM before that became a API others could use? I don't know.

Guest 2

Some of the originators of the web components specs would probably know that, like Dimitry Glaskov and friends.

Guest 2

I suspect it was. It was also informed by XBL 2, which

Guest 3

I know almost nothing about, so maybe that term came from there From, like, 2 decades ago. Yeah. Yeah. So okay. So with the creation of web components, you know, we've been now given access to these APIs to create our own, custom elements.

Guest 3

And, but from from the jump, from the creation, of these things, Dude, people like Google I don't even have to speak on the entirety of Google, but someone like yourself, was the intention Tension for the web components to be authored, to be used straight up, or was there an intention for a layer like lit or something on top of web components as to be the authoring experience. Like, was web components as an API supposed to be the authoring experience, or, was there a vision of things consuming web components to make the authoring experience, maybe a little I guess now it feels More streamlined compared to React components or whatever, but is was that always the intention to author web components as they are? I think it depends on who you ask. I think,

Guest 2

In my point of view, the answer is clearly, time dependent and no for the time being. Right? And this goes back to things like the, the extensible web manifesto, which was saying, you know, Build low level APIs that help explain the platform so that people can use those to build higher level concepts on. And from that point of view, it's like, well, what you really need is a way to tell the browser, Here's the class that defines an element, and here's where to put the DOM.

Topic 4 09:34

Were web components intended for direct use or with a layer like Lit

Guest 2

And then everything else will kinda be layered on top. Although there was, you know, definitely an intention with the web component stuff to basically, envision what these stacks, these layers could be and start from the bottom and move up. So, hopefully, we get to a point where native APIs do give you all the DX that the libraries do. And and, actually, this is kind of one of our philosophies on lit is that lit's often described as unopinionated, but I actually think it's we're quite opinionated in that we try to think about what the features would look Like, if they were actually added to the browser.

Guest 2

Like, what would the API shape if the brow would look like if the browser did it? And we try to implement that Kinda being like a speculative polyfill in a way. Yeah. So do you do you ever envision a world where that actually becomes A reality like that type of API makes it into the browser? Oh, definitely. I mean, I think it makes a lot of sense. It Solves a lot of problems that people have repeatedly and that these are cow paths that the platform should pave. Now whether it looks exactly like lit, I don't know. But, like, We've definitely tried to, you know, just add the things that you need to raise the web component APIs to kind of the table stakes and what you would expect out of A declarative component system. So declarative templates and reactive components

Guest 1

is mostly what we do. And, yeah, I think the the The browser should definitely have declarative templates. Like, everybody's doing some template kind of thing in the browser and updating it. That's funny. Like, I've I've been saying that for a long time, and it I've said a few times in that teaching people JavaScript. They put variables into HTML or or into template tags that then get put into the DOM, and then they're surprised when it doesn't update, and then you say, well, we don't really have that in the browser just yet. You can you can do getters and setters and Or you could use like, a lot of people say use lit html, which is part of lit, but you could just get the the benefit of the the reactive templates without having to use any of the other stuff.

Guest 1

That's exciting that you you think that because I'm very curious. What's the query selector all where we went from jQuery to Right. What what it is in vanilla JavaScript right now, what is that for the reactive,

Guest 2

templating in in the web? Yeah. It's it's difficult Because there's a lot of kind of feelings and politics tied up in this. Right? So I think that even just saying that, like, we envision lit as, like, what would a possible browser feature look Like, I bet it's probably bothering some people who might be listening to this right now. Google's Google's controlling the web. Yeah.

Guest 3

Yeah. Yeah. But they'd be happy with JSX in the browser.

Guest 2

You know, I have a long Twitter thread where I go, like, here's why JSX in the browser could be good.

Guest 2

But but lit is basically an attempt to get something as close to JSX The standard JavaScript and no compiler, you know, as you can. Yeah. I mean, we've had some situations recently where we're working on, like, some template APIs with other browser Hunters and some people in Google are interested in this now. And a lot of times, they go look at lit, and they go like, wow. This, like, implements this concept almost, you know, word for word exactly the same. And I'm like, yeah. Because the 2 ideas grew up together. Like, you know, lit was made to kind of implement the ideas behind the template instantiation proposal.

Guest 2

You should probably drop a link to that in here somewhere, but it's a proposal from Apple on adding reactive, templates. Well, not necessarily reactive, but updatable templates.

Guest 3

And, you know, we designed lit to be like, okay. Like, what if what if this was there? How would we use it? What would that look like to end users? Let's give a, like, a high level What is lit for the people who may have never heard of it and who just heard us drop in lit left and right here?

Topic 5 13:30

Overview of what Lit is

Guest 2

Right. Yeah. Hopefully, I described it in one of those sentences that went past that we basically just give you, declarative templates that can be updated with minimal DOM updates, and a reactive, custom element based class. And so by that, we mean that, like, you can define properties on your class, and when they change, we will, enqueue and update. Like, we use a microtask for that.

Guest 2

So if you have a component, you had to find a property on it.

Guest 2

You you you can use a JavaScript API or a type Script decorators to define the property. And then if somebody uses your component, sets the property, it'll queue an update. When the update happens, it'll update the template with the new data. Only the minimum Dom APIs apply. That's, like, 90% of it, really. Just those 2 things. We end up having to add a lot more stuff because people expect an entire ecosystem around This and so they need all the things that a framework usually gives them, but the core is just those 2 concepts.

Guest 1

Yeah. And for for anyone trying to imagine it, driving your car right now, it's class based. Correct? And you use, decorators On the classes to basically take a regular JavaScript class and add things like,

Guest 2

rendering and and state and whatnot. Well, we have a base class, and and the base classes, you extend element. We use classes because classes, honestly, The HTML element is a class. That's how you do it in the platform.

Guest 2

There are some functional wrappers around lit. But, also, classes are just a great way to combine behavior. I mean, that that's what they do.

Guest 2

Yeah. So the base class implements this kind of reactive life cycle like batching updates.

Guest 2

And then you can either use TypeScript decorators or you can use, like a little metadata object in plain JavaScript, to define properties.

Guest 2

And what that does is it makes a getter and a setter for you on the class, and all the setter says is, like, set the property and then ask for an update. It's like 2 lines of code. So the decorator is just a little convenience to give you that declaratively.

Guest 1

Yeah. The decorator doesn't doesn't do much. Doesn't do a whole lot. That's actually really neat in that, like, maybe people who are listening don't understand what getters and setters are is that, when you have an object or a class or anything like that, you could define a a property like name.

Guest 1

And then when you set that property, You can actually just run custom function that will validation or or anything like that. And then when you get it, you can Return it or do some data, do some work and then return it. That's really cool because you can then hook into the get and set Events that regular people in your JavaScript app are doing. Like, you could say, like, person. Name equals Scott, and then internally in Lit and and whatever. You know when those variables are updated. Right?

Guest 3

Yep. Yep. Does I I think a question that some people might have coming to, some of the stuff from maybe a framework world is.

Guest 3

Does using a library for web components Kinda defeat the purpose of using the platform, or is it is it just there to augment? Are you are you able to have a library with, a smaller footprint because of this. Like, what are the benefits of using a library for web components over

Guest 2

just using a straight up web component? So I think there's 2 questions there. Like, 1 is, you know, like, should you use libraries for web components? And the other is, like, how do web components compare, I guess against against frameworks there. For the library question, you know, obviously, I make a library to make web components. So I think it's more than acceptable to do that, and I think it's actually part of Part of the vision for this kind of phase of how things develop.

Guest 2

You know, in general, I think there's a big debate in JavaScript land about whether dependencies are, like, Good or evil.

Guest 2

You know, not not to be that meme about, like, senior developer. The answer is always it depends, but it depends. Right? Like, good dependencies are good and bad dependencies are bad.

Guest 2

I think that, a library that helps you make a web component is just a dependency.

Guest 2

Right? It should be small. It should not infect the rest of the page, like, the rest of the ecosystem. This is what we try to do with with lit. And I don't think it defeats the purpose because the idea with web components is that the implementation is encapsulated.

Guest 2

So as the user of the web component, you shouldn't care what it was implemented with.

Guest 2

You know, you might care that what it was implemented with is fast and small.

Guest 2

Right? The things you can observe externally from the component. But whether or not it uses, you know, lit or stencil or vanilla inside, really, it doesn't matter too much to the user.

Guest 2

There's some people out there who wanna see web components as the savior for, like, no build, no dependency.

Guest 2

Like, open up notepad dotexe and go. And you can use web components that way, but, you know, lit is not that. Right? Lit is like you import lit and use it, and and we think that's a great option. Yes. So to answer the 2nd part of that question, which I think was, like, you know, why use web components versus a library? You know, web components can help make Your framework's smaller. Right? Like, it takes care of style encapsulation and and DOM encapsulation composition, the component model itself.

Guest 2

But I think, like, some libraries have shown that they can, really, really focus on size and get that down to be comparable to a web components based library. So I think it might be easier to be small with web components based, but it's certainly not like a unique advantage that's unassailable to to web components.

Topic 6 18:39

Benefits of using a library with web components

Guest 2

The the thing that web components are really there for is to enable interoperability.

Guest 2

Right? And a number of different types of interoperability. Right? Like, between frameworks, for a component that's stand alone between developers, Right. As a for for for components on the web, and oftentimes between Different versions of yourself for a project, like a future version of your project.

Guest 2

You know, we see projects I see them all the time in Google that, like, have to migrate from one Framework to another, and it becomes a really disruptive affair where features have to stop while they try to migrate the whole thing.

Guest 2

And, that should just be unnecessary. Right? So in the future, if you decide to change, if you're building to interfaces and encapsulation, you should be able to do that change incrementally and not, like, Stop your whole development process.

Guest 2

So I think those are good kind of software engineering, you know, best practice basis for using

Guest 3

An interoperable component model. I think that's huge. Yeah. And I don't think enough people talk about how huge that is because I've started to move Specifically, UI components, things like video player, toggles, those types of things that, like yeah. I mean, we have, we we don't have Those individual elements in the browser necessarily to have a like, an HLS streaming video player. Right? We have a video element. But to be able to have An HLS streaming video element that I can take from project to project regardless of what it is or reimplementing this or not having to worry about the version of the software that I'm using this thing in. It is based on it's a web component. It works everywhere. It's it's been a huge thing for me personally, Especially with the the smaller things. And then I'm working in a framework, so I'm laying that framework handle bigger tasks, Client side routing and rehydration, whether that's good or bad or whatever.

Guest 3

I'm laying the framework handle those elements of the thing rather than The individual UI components, and that's huge,

Guest 2

to be able to to do that. That's a clear, like, advantage and great use case for web components. I mean, To me, it also applies to entire apps. Like, you never know which part of an app you're gonna wanna reuse somewhere else or when you're gonna wanna migrate. So I'm like, let's just make the DX the same as for frameworks and then just use it universally.

Guest 1

Is there, like, limitations to using, like, a web component in other frameworks? You know, like like, maybe even Scott can can answer this one. It's like, why would I write it in React when I can write it in even if I have a React app, why would I not just write it in A a web component. Is there, like, some sort of limitation that it would hit, or is it a little bit weird? Or is the the life cycle events don't line up? Or, like, is there something there that Not why is not everybody doing this? Yeah. I mean, there's some reasons.

Guest 2

Actually, Rob Dodson, who used to be a Chrome, DevRel, person, made this awesome site that we still keep going called Custom Elements Everywhere, and it basically tries to document web component compatibility with frameworks.

Guest 2

And, for the most part, most frameworks do extremely well.

Guest 2

Sometimes, some have some problems. So, those usually stem from the framework making, Assumptions about the DOM. So assuming it's a closed world and it knows about all the tags and special attributes and stuff like that.

Guest 2

React, for instance, has a problem, adding event handlers or setting properties on Custom elements. Right? Because they assume if you're using the lowercase JSX tag name that you can't set properties. You can only set attributes.

Guest 2

React doesn't have a way of adding arbitrary event handlers.

Guest 2

They assume that everything has to have an on click or or property that you can set.

Guest 2

Yeah. So that makes it so that, you know, you might have to use a ref to actually use the web component correctly so you can set a property.

Guest 2

They're fixing this In an upcoming version of React, hopefully, React 19, but we also have, like, a wrapper that we provide that will Fix that kind of stuff. So that's generally where the impedance mismatches, that are out there come from. Yeah. And in my experience,

Guest 3

especially libraries that don't use a virtual DOM, work really well. Like, Svelte works really well. I have access to the DOM. Just drop it in and unmount and initialize it and bingo bango.

Guest 3

Everything just works.

Topic 7 23:14

Using web components in frameworks that don't use virtual DOM

Guest 1

And does lit has, like, a whole life cycle events

Guest 2

For things like when the data is updated or or when somebody clicks. Right? Like, they there's no difference to that? Or how does that work? I once did an examination of all the different life cycles of all the frameworks and, like, laid them out in the big table, and they mostly line up. I mean, the, component life cycle is a is a cow path to be paved at this point.

Guest 2

So, what lit Gives you is is it kinda adds some phases to the life cycle on top of the standard custom elements life cycle. So custom elements gives you, connected and disconnected and then attribute changed, and, and you have the constructor in there.

Guest 2

Then you could also layer on top of that setters as a life cycle, like, for individual reactive state changed. And then lit gives you, like, what we call the reactive, element life cycle. So we give you a should update, will update, update, and updated kind of phase that things flow through. And then it gives you a render method that gets called during update, and that's where you put your template.

Guest 2

So, again, just kinda augmenting the standard,

Guest 1

life cycle. And what about, CSS? How does like, I know web components have the ability to do Scoping CSS. Can you explain how CSS works in web components

Guest 2

and lit specifically? Shadow DOM is kinda responsible for all the heavy lifting here.

Topic 8 24:35

How CSS scoping works in web components

Guest 2

Shadow DOM gives you a scope. So if you put a style tag into the DOM instead of a shadow root, those styles do not leak out of that shadow root. So they don't leak. We call it, upper and lower bounds to to scoping.

Guest 2

So they don't leak above the component, meaning, like, the opponents, component's ancestors. So if you if you style a paragraph tag, it won't style the page.

Guest 2

They also don't leak down into nested shadow roots.

Guest 2

So component defining styles won't automatically style the contents of its nested children. Right? They can style the child, but not the Child's shadow children.

Guest 2

And so that's just in the platform. It's it's runtime encapsulation. You don't need a compiler. You don't need to agree to, like, You know, munge the class names the same way or use BEM or anything like that. What about what if you do want the styles to cascade? I'm thinking about, like, alright. I want to set all the fonts to

Guest 1

Verdana, justified. And I want everything to do that. Is can you set global styles, or can you say, I do want these things to Cascade down into my component. So that gets that gets a little bit tricky. We're we're still working on some things there. But the the most basic thing is that,

Guest 2

inherited CSS properties Do inherit across the shadow, dawn boundary.

Guest 2

So, there's a bunch of inherited inherited properties out there.

Guest 2

Font family is one of them. And, color is another one. So if you look on MDM, it'll, I think, show you if the property is inheritable.

Guest 2

So if you set the font for the page, that will apply, throughout all of your shadow roots. Right? So you get some visual consistency.

Guest 2

Also, c CSS custom variables are all, inherited.

Guest 2

So they flow through all the shadow roots. So that's probably the main way people do this cross shadow root styling now is they set a bunch of CSS properties and then apply them.

Guest 2

Selectors, though, don't cross the shadowbound boundary, and that's where things get, you know, a little more complicated because it's hard to figure out what the developer actually wants In these cases, like, do they want the encapsulation, or do they want selectors to apply? There's a thing called CSS shadow parts, which is, the colon colon part, like, pseudo class, if you ever see that out there. And that allows a component in a shadow root to kinda designate Some of its Shadow Root elements as stylable from the outside.

Guest 2

And then on the outside, you write, you know, my element colon colon part and then a part name, and now you can style that Cut element. Oh, and is that how

Guest 1

we will eventually be able to or or or maybe already is style things like the video player and select Drop downs and maybe one day I pray the date picker, or is that something totally separate that the browsers have to decide? Well, it's very analogous to pseudo classes.

Guest 2

I mean, it basically is custom pseudo classes. So, you know, where you can do colon colon placeholder to style, you know, the color of the placeholder text in the input, Colon colon part just lets you do that, for for things inside of shadow roots. Okay. Okay. I see that. And

Guest 1

you can create just, like, reusable, For lack of a better word, styled components inlet where, like, if you do want to reuse, like, let's say, a specific button or something like that, you could just import those into your thing and and go ahead and use them. Right? Yeah. I mean, we,

Guest 2

we try to make our components kinda being like, you know, they bring There's styles with them? Yep. Yep. Yeah. The way we do that is we do CSS and JS, basically, but we do it very, very differently from everybody else. It Avoids the pitfalls that people usually associate with that. So the browser has this feature called, well well, it's rolling out to all browsers now, constructible style sheets.

Guest 2

And what that is is the ability to just create a style sheet in JavaScript. You just go new CSS style sheet. Once you do that, you can add it to the document or a shadow root.

Guest 2

So what we do is we give you, this CSS backtick template

Share