Before the dawn of some of the most popular frameworks (read: React and Vue), there was Web components. Web Components take one of the best parts of these frameworks (reusable components) and combine it with the best parts of web development (native browser support and not needing to set up a build process). As if that's not enough, web components allow you use the same functions across any framework.
If at this point, you're wondering "If web components are so awesome, why haven't I heard about them before?", then you're in luck because that's exactly what this talk is about.
In this presentation, we'll take a look at what web components are, why web components are awesome, why web components can be a pain and how we can use web components both as a standalone tool and together with frameworks.
Transcription
Hi, everyone. My name is Jemima. Jemima Abu. Let's talk about web components. So I should probably introduce myself first. I'm a self taught front end developer and school taught systems engineer from Lagos, Nigeria. I'm a long way from home. But I live in London now. So not that long. And you can find me online anywhere. So that's LinkedIn, Twitter. I make my user name easy so you don't have to go to stress to stalk me. It's all there. All right. So let's get into it. Web components, what are they? So I'd like to preface by saying why I wanted to give this talk. I like to build things with HTML and CSS. I'm not a huge fan of JavaScript. When I was first learning React, I didn't understand why things were the way they were. I didn't understand why I had to use set states to change a state property. But you couldn't just change it as a variable. It didn't make sense to me. So personally, I prefer using HTML. What I don't like about HTML is how if I want to create six blocks of the same thing, I have to copy and paste the same thing many times over. That's what I do like about React. I was like, is there a way to have the simplicity of HTML with the reusability of React? And the answer was web components. So basically web components are a suite of technologies that allow you to create reusable HTML elements. So right off the bat, they're already there in your browser. You don't need to do any installation. It's like using vanilla HTML? Is that what it's called? It's like using regular HTML, but with all the fun of React. And how does it work? So, first of all, we have our custom elements. Custom elements are an API that allow you to define new elements and their behavior. So you can create your own HTML tags to use. And then we have the shadow DOM, which sounds very cool and I like it. Which allows you to encapsulate elements, functionality, and style. So this is what allows you to remove your custom elements from the regular flow of the page and just have it in a different DOM. Which is fun. And then finally we have HTML templates. So these are the custom tags that you're actually rendering on the pages. Yeah. So I was going to go through a little bit of code to show, like, what I'm talking about. So this is like a simple blog template that we create in regular HTML. So if you are using regular HTML for this, it's just a lot of copying and pasting and changing the content. So let's see some code. Which is the part I'm good at. All right. So first we're gonna look at what it looks like in regular HTML. So we have this... We have our code up here. And the regular HTML is literally just a lot of pasting of the div with the same content everywhere. So you can... I'm gonna zoom in. There we go. So you can see you just have the post div, and it's just repeated multiple times throughout the page. Because that is what HTML does. It doesn't give you variety in how you decide to code. And then we have the method I usually use when I'm trying to repeat things. So on my portfolio page, if I was trying to repeat the websites I've built, because I use basic HTML to build my portfolio page, instead of having to write them all at the same time and then just changing the content, I usually just create an array with all the content I need, and then I render that on the page using vanilla JavaScript. So if we're going to do that for this... Hard scroll bar. If we're going to do that for this thingy, it would look something like this. I was meant to be live coding, but then I realized that's just... I'm not brave enough to write code live. Things will go wrong, and I will break down. And I'm not doing that. So if you were doing this with vanilla JavaScript, it would be something like... You define your post. So this is basically all the HTML that was repeated previously. And we just have it inside a function. And then you just render it in the page. So in this one, I did it with a button that you can click to add new posts. And then you can add as many as you like. But then when you render it with a page, it's pretty much just defining document.createElement, and then appending that element to the container that we want our code to be inside. So that's pretty much how this works with vanilla JavaScript. So this is the basic idea behind Web Components. It's taking your HTML and appending them to your DOM. But then because the idea behind Web Components is being able to have encapsulated and reusable components, it's like a bit of a mixup. So we'll see how we can get a bit more complicated than this. By going back. So let's talk about custom elements. Custom elements are the first part of Web Components. And as we have said, they are elements that allow you to define your own HTML tags. So this is what defining the custom elements in JavaScript would look like. You define your custom components as a class. And then use the custom elements API to define this new class that you've created. And then you can call it in your HTML using your custom tag. So it's like fairly straightforward. So custom elements allow you to define custom HTML tags. The only syntax is that they have to have a dash in them. So you have your custom elements.define. And the one with the dash is the HTML that you will render on the page. Then you render your custom HTML tag in the DOM. And it also has a lifecycle method. So let's take a look at what a custom element would look like if we were putting it in the DOM. Yeah. Going back. Yes. Custom element. This part I will write a little code. So I can delete that. All right. So like we said, when you want to create your custom component, first of all, you have to define your class. So I'm just going to create a class. And I'm going to call it a post component. And you use the extends keyword. So it's pretty much the same way in React. You would use the extends React component keyword. In this one, we extend the HTML element keyword. Totally forgetting what the syntax is. Yes. Is there a dot? Is there not a dot? HTML element keyword. And then that's pretty much it. Because it's a class component, we do have to initialize our constructor. We just do your constructor and you call your super thing. And that's that. And then when you're working withοΏ½ I feel like this is very common for people who use React a lot. I would just like to say I'm very glad functional components are a thing. I was not a fan of class components. So once you've initialized your constructor, then with custom elements, you have your own lifecycle methods, the same way you have, like, use effects in React. And custom components, it's calledοΏ½ it's called something callback. Well, anyway. I can't remember. I'm not going to stress myself. I'm going to put it in here. So basically what we want to do is we want our class to return theοΏ½ thoseοΏ½ the content that we had in our page previously. That made the post. So you can just createοΏ½ we're going to set this in our HTML. So this is going to targetοΏ½ once we initialize the post component on the page, it's going to target that post component and set the HTML to whatever we're defining inside this template literal. So let's put a title. Yep. Give this a class title. I'm just going to call this post title. And we're going to give it some content. And put some lorem ipsum in there. Because if you don't put lorem ipsum, you're coding. And then we're going to give it a span. And finally, we're going to define our custom element here. So it's going to be custom element.define. We pass in the name of our custom component, which is post component. And then we pass in the class component we just created up there. All right? And then finally, when we want to call that component, we just pass in the actual thingy. I have to close this. I have an error. That's fun. Let's see. Of course not. That would be too easy. All right. No. I need to define it. Pause. Fun fact. It's elements, not element. There we go. All right. So we're going to define our custom element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. And we're going to call this element. You take my word for it. You can turn on the shadow roots. And somewhere in this panel, there's a keyboard. There's a little check button like this that allows you to show what shadow roots elements are. And for video tags, that's how they work. They are not part of the DOM itself. They are in their own little iframe thingy. And that's why they don't get affected by... I'm closing YouTube before it gets weird. That's why they don't get affected by global styling of elements. And shadow DOMs allow you to set style and markup without affecting the global DOM. So it's the same thing with the videos. Videos have their own styling. But whatever styling is encapsulated in the video does not affect any other styling on the page. It's just trapped in that little video tag. And it allows you to interact with the shadow roots, which sounds very cool. Which is why I put it there. So let's take a look at how the shadow DOM works. So here we have our custom elements. So this would be... we can see we have a post component here. And this is what a normal post component would look like. But what we want to do now is create a new instance of the shadow DOM. So... let's scroll down a bit. All right. And then we're going to create our new class shadow... I'm going to leave the commented out code there. Because I am scared of it not working again. So I will have something to reference. So we create our shadow element. We initialize our constructors. Yep. We initialize our constructor. And in here, this is where we call this dot attach shadow and mode open. So the mode... the open shadow mode is what allows you to actually interact with the shadow DOM. If it was closed, you wouldn't be able to add any elements to the shadow DOM. That's what people usually use for embeds. So if you try to embed an iframe and you try to maybe style it or something, and you couldn't, it's usually because the shadow DOM is closed. So by them closing the root, it means you can't interact with that element at all. So that's how this works. And then we can have this dot shadow root. So we need to create an element. So we create a const, let's say shadow div equals to document dot create element div. And we can pass in random HTML to this. Dot inner HTML equals hello React advanced. And then this dot shadow root dot append child. And let's pass in the shadow div. So this would be the... this is the class constructor for our shadow components. We still need to define it using custom elements. So we can... Are you happy now? There you go. So we can define it using custom elements dot define. And this is going to be shadow comp. And we're going to have the shadow component class. I always forget which cases I use, but this is this one. All right. And then let's see if this works. Shadow component. Thanks. That's what I get for changing things on the fly. All right. So there we have it. But then the important thing about this one is when we go to our actual DOM, you can see that in the post component, it was just part of the page. So it wasn't really, like, separate from the DOM. In the shadow component, it's opened a new shadow root. And you can see that here it says to open. And we have our div passed into here. So this is an example of how you would initialize a shadow component. But now we have to show, like, how the styles of a shadow component would be encapsulated from the rest of the page. So this is our... I'm going to style this the same way this one is written. All right. So something else we can do with custom components is you can also pass attributes to custom components to be rendered as data. So the same way in React you would initialize a... Let's say this was a post component in React and we just set value to whatever value we wanted rendered. We can do the same thing in custom components using JavaScript. So up here we have our connected callback. That's what it's called. I was like, connector? I don't sound right. So here we have... We're basically going to get the attributes and that's what we set to the component we want rendered. And then when we call this component, we're just passing the attributes here. So here we've passed in title custom components and data text, hello, React, advanced London. And that's what's rendered on the screen here. So we can do the same thing for our shadow components. Once you call your super. And this dot attach shadow. So we can leave all of these in our constructors and put all of this in our connected callback. The connected callback is pretty much the use effect of web components. Once your page has loaded fully, once the element renders on the page, then whatever is in connected callback is called back. So we have the shadow div. Okay. And we have our shadow.innerHTML. And we need to define all of these. So we're going to have const title equals to this dot get attribute title. And if it doesn't exist, make that null. Same thing with const data text. This is going to be this dot get attribute data text. If it doesn't exist, make it null. And then we're going to set date to be a new instance of whatever date the component is rendered on. There we go. All right. So this is what we have on the screen now. And then once we initialize the values here, title equals to shadow element. And data text equals hello, React, advanced. And then. All right. So we have this set up now. I'm just going to switch up the data text so I can have something fun. Data text dot split dot reverse dot join. So our shadow text is going to be a mirror of our post. You're undefined. There we go. So our shadow text is going to be a mirror of our post. Now, if we look in here, we can see that even though we have defined this inside a post class. There we go. So this is in a post class. So technically it should have all the stylings of the post elements that this one up here has. Because we can see that we have styled our post element. Once I scroll up. We've styled our post element here. But the shadow DOM does not get any of that styling. Because the post element was styled in the global DOM. And that doesn't trickle down to the shadow DOM. So when you create shadow elements, if you want to style them, you also have to define the styling for the shadow elements in your custom components. Which is kind of annoying. But it's also fine. So that's what we're going to do now. We can. How do I want to do this? Okay. We can set an attribute. Here. We can pass this into this element as well. We can create a style tag here. And this style tag can have, let's say, Post and order. There we go. So once you have defined your style tag inside the shadow elements, it only affects the shadow elements. And you can see that it did not affect the styling of the post that was in our global tag either. So that is how encapsulation works. They are both elements that are rendered on the DOM. And the user can see both of them. One is just kept separate from the other because it's the shadow DOM and the other one is the custom element. So that is how the shadow part works. And then we can go on to HTML templates. So HTML templates are a specific tag that don't show up on the HTML page. And I'll explain what that means. So basically, if we have this template here, this isn't going to show up on an actual page. So let's just take a look at going back. Let's take a look at this real quick. I'm just going to pull this out. So here we have defined our templates. So for all intents and purposes, we don't have any JavaScript on this page, but by default, the template tag does not render on the page. If you open up your DOM, you will see the template tag in the DOM, but it's pretty much just empty. Yes. So here we do have the template tag, and we have all the elements that should be inside it, but by default, the template tag does not show up on the DOM. It's just set to display none, and it's empty. All the elements are stored inside something called a document fragment. The fragment is basically just a piece of the document object model that is stored in the template tag. Template tags are basically placeholders for contents that you want to render on the page at a later time. So anything you put in a template tag can be called after the page has loaded using JavaScript in your custom components. I'm going to be honest. I didn't get this. I was like, why? What's the general idea? But I guess the point is just that it's the same way you have semantic elements that serve a certain purpose. Template elements serve the purpose of not rendering on the DOM. That is just its burden in life. So let's take a look at some JavaScript. Using... Yes. All right. So first we define a class web components. This is going to extend. So same thing we've been doing since we're getting our custom components set up. We have our constructor. And we have super. And then we have our connected callback. So with the template function, when you're calling a template function, you have to actually target the specific template function. The difference between the template function and what we've been doing so far is that we have been defining all these contents in JavaScript so far. We've been calling, we've been creating divs and everything inside JavaScript. But now we actually just have it in the DOM itself. And we're going to render it here. Also in the DOM. But then we also need to put it in the components. So we have our connected callback. And we're going to get const templates. And that's going to be close to document.getElementById. Oh, dear. Okay. I'm good. ID, what was the name of this? HTML template. Yes. HTML template. Another thing with the template tag is that it doesn't work the same way regular elements work. So with regular elements, if I wanted to get their contents, I would just use inner HTML. As we've seen from the thingy here, components do not, templates do not have inner HTML. What they have is a fragment, which can't be targeted just using inner HTML. So how we get the content in an HTML tag is by using template content. So we target the template. And we target the content. And then we create a node from this content. So basically what's happening here is we can make that deep. So let's take a look at each of these things individually. I'm going to throw everything into JavaScript because that's how I work. Content. And the first thing to define is custom elements.define. Web component. Web components. So arguments required, but only one present. That's not right. Hmm. What? Freak. Frack. How many minutes do I have left? Zero. Minus five. Well, that's the thing with demos. You're like, oh, it will take like 10 minutes. And then you're like, it's been 30 minutes. And you're like, what? All right. Let's wrap this up then. So I'm going to run through the code for the rest of the HTML templates. But also I do have all the code already set up on my code pen. Because I'm the kind of student that did the assignments before the teacher assigned it. So if you want to take a look at it, I have the links to those in my slides. I'm going to run through the rest of it. I'm going to get to the actual React parts. So yeah, HTML templates, blah, blah, blah. This, that, that. YWeb components are awesome. They allow you to use reusable HTML elements. Love that. Also, they do not require any installation. So you don't need to set up a build process or anything. You can just use them out of the box. And my favorite part, they are cross-framework compatible, meaning that you can use your web components in, you can define one web component, use it in React, Angular, Vue, any framework, and it will work. React versus web components, which should you be using? The React docs puts it best when it says, React and web components are built to solve different problems. So it's not a versus. It's not a this or that situation. It's a this and that situation. We're looking at how best we can combine web components with React and get it to work. So both. Both is good. Yes. So there is a website. It's called Custom Elements Everywhere. And it shows you how elements, how custom components work with each framework. So you can see that for Angular, it has a score of 100%. It integrates perfectly with Angular. For Vue, it has a score of 100%. It integrates perfectly with Vue. For React, eh, could be better. Basically, the problem with that is because React does not allow instant, it does not allow you to interact with the DOM the way web components do. So if you are trying to pass a web component, like if you're trying to, let's say we define a button in a web component and we have an onclick event, that is not going to work the same way that things work in React. Because React is React. But yeah, we were going to have a demo, which was not all the code I was showing you earlier. It was going to be a different demo, but we can't do that now. But if you guys do want links to, if you want the link to the slides, I have that up on my website. It's jemimaabu.com slash talks slash web components. And if you have any questions, I don't think I have time for questions, since I used up all my time. You can reach out to me on Twitter or on my website, jemimaabu.com. And I hope you found the talk interesting or that you learned something. Thank you very much. Thank you.