 All right, so there's been a lot of talk about web components to this presentation, so I'm excited to be able to talk about what that means in terms of how we use Backbone and how we build our web applications in the future. So I have a bit of a click-baity title there, Game Changing Combination, but I think the technologies and web components will really try and change how we approach web development going forward. So my name is Andrew Rota, I'm a JavaScript engineer at Wayfair.com here in Boston, and I get to work with some really exciting technologies every day, JavaScript, HTML5, Backbone of course, and that's really cool. And so for the past few years, I'm constantly thinking about what's next in JavaScript, how can we apply the tools that we have today to make really cool products, but then how, going forward, can we be prepared for the future? And there was an article recently called the State of JavaScript in 2015, a few weeks ago, by a developer who was talking about, you know, what are the lessons that we've learned, and where do we think we'll be over the next year and the years going forward. And he made a really good observation and he said that, you know, components with a dedicated purpose in a small surface area are really advantageous. They allow us to take pieces of our framework, mix and match them, swap them out, and be really modular and flexible in building our applications. And I think this is a philosophy that we really share in the Backbone community. But I think about how we use modularity in the web, and there are all sorts of different ways, whether it's on the back end or the front end, but on the client side, one of those ways is simply HTML. We've had DOM elements for a long time, and they're actually really modular. And that's kind of cool. You know, for example, let's say we have an unordered list. Make sure that's big enough. Everything's big on this screen. Yeah. Let's say we have an unordered list. It's really easy to go ahead and convert that to an ordered list. Like, you just change one character. And that's nice. I don't need to worry about breaking APIs. I don't need to worry about, you know, any big changes there. You know, even if I have something that's a little more complex, let's say I have a header with a whole bunch of stuff in it, when HTML5 came along and we had the new header element, I'd go ahead and throw that in there. And it wasn't really a big deal to switch it out. Same thing, say, with my navigation. Maybe this was a list. Maybe it was a div, or maybe I had a rather complex component. But I could go ahead and swap it out. And that was really cool, to be able to kind of see something new and not have to think, oh no, I'm going to have to rewrite my entire application to get this new technology. And so in this same article on the state of JavaScript in 2015, the author made the observation that, you know, maybe it's that libraries are greater than frameworks. And I, again, think this is something that we would agree with coming from a backbone place. But I kind of, thinking about this HTML modularity, thought we could take it a step further. You know, native functionality, I think, is really the most modular in terms of building out applications. And, but that's not possible, right? We can't, like, make our own HTML elements until now. So that's what web components are about. Web components are really this new HTML5 technology that allow us to create truly encapsulated and interchangeable components that extend HTML itself. It extends the functionality of the DOM. And this power is now given to us as developers. This is a quote by the Polymer project, and I think it's a really accurate description of the impact of web components. And so web components really aren't one big thing. You know, like HTML5, it's a collection of a whole bunch of different things. And so there are four main kind of technologies or APIs that make up web components. So I figured we'll start just by going through each one of these. So we have custom elements. That's probably one of the more interesting ones. So custom elements is this idea that I can go ahead and make my own HTML elements and register them on the DOM and use them as if they were a native element. To do this, I simply have to call document.register element. I pass in the name of the element, and then I pass in an options argument that the important option there is the prototype for my element. So in this case, I'm going to go ahead and just make a new object that sets the native DOM HTML element as my prototype. So I'm going to sort of get the basic package for a DOM element. So this is going to act just like a div. But that's actually native DOM there. I can write that in my HTML once I register this element. It's not like any special library or something to transpile it. It's just going to work. One thing to keep in mind about the name there is it does have to have a dash in it, and it's something that the spec authors decided would be a nice way to separate custom elements from native elements so we don't have namespace conflicts. But other than that, I can go ahead and namespace my elements however I like, name them whatever I want, and actually create an element I can use. So that's custom elements. The next technology are HTML templates. So HTML templates are actually a new element in HTML called template that allows us to put nodes on the page that we want to be used later on. And so when we actually place a template tag, anything within that template tag is going to be inert until we activate it by cloning it to use it in our document. So don't think so much about handlebars templates or mustache templates or underscore templates. This is a little different. It's not going to have that data binding or functionality or logic that you might be used to in templates. This is simply the bare bones DOM elements. And it means that you can store these in your DOM. The image won't be downloaded here because it's going to be completely inert when it's added to the page. And then to go ahead and activate it, I can clone it with document.import node, pass in the content property of my template object there, and then just pass in the second parameter true to tell JavaScript this is going to be a deep clone. So that's HTML templates. The next HTML web component technology is HTML imports. And this is the ability to actually import documents into our application with a link tag. So no longer our link tag is just for CSS. We can use it to pull in HTML documents directly. And in this animation here, it actually is just showing the documents filter on the network tag in Chrome Dev Tools. And you'll notice that we have a whole bunch of documents here. Normally, you'd probably only just see one where actually can pull in different HTML documents directly through the browser and use the browser's native mechanisms to pull these down. It's going to follow the same cross-origin request security rules that you're used to. But it's going to use link directly to pull these in. All right. So the fourth web component technology is a Shadow DOM. This is probably one of the more interesting ones, because it means that we can actually create a tree under our normal nodes in HTML that contain other HTML nodes. And it takes a little bit to get your mind around this. But I think a good example is something that the browsers have been doing for years. The browsers have been taking complex elements and implementing them with Shadow DOM nodes underneath that we don't see. When we look at our source, we don't normally see them. And so we can actually take the video element as an example. We can turn on user agent Shadow DOM. And here we see the video element that used to be just one element now has a shadow root and underneath that are a whole bunch of divs. And within those divs are more divs and inputs. And that kind of makes sense, right? Because we have controls here. We have a play button. We have a progress bar. We have the little timestamp. So there are a whole bunch of things going on that we sort of just assume that's how the browser works. But they're actually building this up with DOM elements. And they're putting them under the shadow root, so they sort of encapsulate them. We never see them unless we go ahead and turn on our dev tools to allow us to see them. But that's kind of cool. And it's not just encapsulating the HTML. These styles are actually going to be encapsulated too. So if you're coming from a CSS background at all, you know that encapsulation with CSS is pretty much impossible. We can sort of fake it with different patterns, and we can kind of increase our specificity and try to apply styles only to a certain area. But they're always going to leak out. There's always a possibility that DOM nodes somewhere else on the page will be impacted by our styles. But with Shadow DOM, that's a little different. So if you can think about taking a video element on your page, there's nothing I can do with CSS to make that play button blue. I can't change the color of that no matter what I do. I can put an important and I can make a super specific style. It's just not going to happen. With the Shadow DOM, you can actually protect and encapsulate your styles under your shadow root node. And so that's really powerful. And very basic to see how this works, we have an empty div first, and then I have a paragraph tag. We refer to the DOM outside of the shadow as the light DOM. So we have the light DOM in a paragraph. We have an empty element. I'm going to go ahead and select that element and call create shadow root on it. Create shadow root. We'll attach a shadow root to it and return the shadow root. So I now have a reference to that with my variable s there. And then I can go ahead and set the inner HTML of that shadow to be a style, to be other DOM elements. And so in this case, I'm actually going to throw a paragraph under there called shadow DOM. I'm going to put some styles in there just to make it red in this case. And if I go ahead and take a look at this, my div is simply my div with my paragraph next to it there. And then within my shadow root, I have my styles. And so those actually get encapsulated just like that video element did in terms of having a shadow root and being able to put styles within it that won't leak out into the outside document. And it goes both ways, that encapsulation. So that's really powerful. Something with these shadow DOM nodes as well as that I can take inner HTML from my light DOM and go ahead and project it within my shadow. When I create a shadow root, normally it's going to take everything that was within my element there and just not display it because it allows you to go ahead and display it wherever you like. So you use a new content element within your shadow DOM to project these nodes from the light DOM as if they were in your shadow. And something to notice here as well, I have that same style tag that's making the paragraph tags crimson that will not affect the content projected within my shadow. Because that's still in the light, even though it's being projected between my shadow DOM HTML there, it's still going to have the styles of the surrounding document. All right, so those are the four technologies that we have with web components. That's it. That's what we have to work with. And you can combine them in different ways. You can use them on their own. They're perfectly useful on their own. You can go ahead and use custom elements, templates, import, shadow DOM. They don't give you a super lot. I mean, we have some kind of game-changing features, I think. I think things like the shadow DOM and custom elements we didn't really have before. And so we get some things. We don't get everything. This doesn't replace all of our web applications. Certainly things that we're used to, we don't have here. We don't have things like application structure. We're just building HTML elements. We don't have any interaction with the server. None of that's built in. We don't have things to route our URLs on our pages. We don't have any models or collections or events to react to changing data on our page. But it turns out we have all of these with backbone. And so I don't think web components replace backbone. In fact, I think they work very nicely together. So let's go ahead and look how we can take each of these four technologies and apply them to our backbone application individually. So we'll start with custom elements. I can go ahead and register my custom element like I normally would. I could do this in a variety of places. And then in my backbone view, I can go ahead and just put the tag name for my custom element in as the tag name for my view. And it's going to work. There's nothing with backbone that makes tag name special to native elements. Because custom elements work the same as my native elements, this is going to attach the DOM element to my view that's based on my custom element. So that's really cool. HTML templates. We can use these to put templates on our page. Maybe you're using script tags to throw templates on your page. Or maybe I've seen templates attached in hidden divs before. They all seem sort of messy, and template can kind of replace that for us. This is certainly not going to replace maybe your server compiled templates. But it could give you a way to access DOM nodes from the document, and you don't have to worry about them being downloading extra content before it's needed. Images or scripts, et cetera. HTML imports in backbone. You don't really need backbone at all for that, because you can use it perfectly fine, because it's just HTML. It's not necessarily a JavaScript API. This is an attached API, but that's not really necessary to use them directly. And then shadow DOM. We can go ahead and use the reference to this .l in our backbone view, which is just a DOM element, and create a shadow root. And we could do all sorts of things there. We could add nodes underneath our view that we wanted to encapsulate from the outside world. We could style them appropriately in CSS. We can even use their special CSS selectors to go through those shadow roots and break through the shadow boundary if I want to select those elements. So these are all great. I can take each one of these individually and use them in backbone. And it doesn't really require a lot of work to do so. But as we saw in the last talk on D3, there's something different between just using things with backbone and using things well with backbone. There are different strategies to combining things. Combining things is easy, but combining them in a way that's useful is a little more challenging. And it's certainly dependent on what you want to do. And the good news about using web components, maybe the reason that you'd be interested in using them, is that there are a lot of really cool web components available out there already. Using the individual technologies are really less useful than using web components themselves. Using components that other people have built, other engineers have built, other companies have built, or maybe you've built within your organization to be used between applications. And there are a whole bunch of these components available right now. Polymer is an application that Google has been working on that's sort of powered by web components. But you don't have to buy into Polymer to use their elements. Their elements are available, and you can use them as web components. Mozilla has a library called XTags, which also has a bunch of open source web components that might be useful to your application. And there are all sorts of user repositories of these components online, and they're only growing. More and more engineers are making components that can be shared across applications. And so what might this look like? What if we want to take a component and integrate it within Backbone? And the first step is going to our Backbone view. This is more about the view layer in Backbone than it is about our models and collections. So let's go ahead and take an example and see what that would look like. So this is a cool little component from the Polymer Paper Library, which is toast. So it sort of pops up from the bottom of the screen there. And it's fairly basic, but it has some styling there. It has some animation. And so the first step to considering how to consume that from a Backbone application is to look at its API. And the API is really the starting point for integrating any custom element into your application. And these APIs aren't any different than our native DOM APIs. They might be a little more complicated, depending on how the element was built. But they're the same thing. And these DOM APIs are made up of three different features. The first are attributes. So these are regular attributes that we would throw onto our tag. In this case, we have the text for the toast. We have the duration that is going to be open. We have an attribute to tell us if we want to close it or not when you click outside of the toast. And then we have an attribute that tells us if it's open or not. And so changing these attributes will change the state of our element. It will change something on our element itself. The second piece of that API are methods. And so these are methods that we attach to our element. We attach them directly to the element. This isn't like some wrapper. This is attached directly to the DOM element itself. So you select the DOM element natively, and you have access to these methods. With the toast element comes with show, dismiss, and toggle out of the box to either show the component, hide it, or toggle it depending on its current state. And then the last piece of this API is events. So we have native DOM events that come with these custom elements. And again, these aren't sort of a custom event. These are events that we're listening to directly on the element, not unlike any other events you would listen to on DOM elements. In this case, we have one that's core overlay open completed, which is just a long way of saying when the animation is finished opening. And so once you know your API, it's fairly trivial to go in and just implement that in your backbone view. This is nothing special. This is going ahead and taking all the native functionality of a backbone view and using a web component, which means you don't need a special adapter. You don't need any real conversion layer. You can just use your backbone view. And from the perspective of your backbone view, this is simply a DOM element. You don't need to know that it was custom. You don't need to know that it was built either internally or externally. You just need to know that it exists as an element on your page and the API that you can work with for it. So in this case, I'm going to go ahead and set tag name. I'm going to go ahead and use backwindupviews attributes hash. I'll actually use the events hash to bind events like I normally would to a custom element. I don't have to do anything special. And then I can go ahead and wrap any methods that I'm interested in. I could certainly use the methods directly, this.l.toggle. I think it can be useful to wrap them if you want to, say, fire your own event or do any bookkeeping or management of different methods on your component. All right, let's take another component that's a little more complicated. So this is a component from Google called Google-map. And it just includes the Google map on the page. And this is a lot easier than using any JavaScript API to pull in Google Maps. You simply have to include this on your page, and it works. It actually defaults to San Francisco here. But I can go ahead and use the API to decide what it's going to show. So I can choose the zoom level. I can change the latitude and longitude to refer to Boston instead. I can use the methods that it comes with. So .resize will kind of re-render the map on the resizing of your window because it might need to get new tiles for the map. I can clear any markers that were put on the map. I can add an event listener for Google Map ready, since it actually has to go and make an Ajax call. So I have an event that I can hook onto and do something with. And then I can go ahead and integrate that with my BackmoveView. And again, this is nothing different than normally creating a BackmoveView. This time we're just using a custom element that happens to be on our page. We've probably used HTML imports to pull this in. And then we can go ahead and consume it within our BackmoveView like it was a normal element. And you don't have to just create sort of static elements like this. You can probably start to imagine the different things that you can do with these views with the power of BackmoveView. So maybe I want to go ahead and bind to the change events on a model. Maybe I have a model for places that have latitude and longitude and zoom there. I can again set Google Map as my tag name. And now I could do something when my model changed. I can move the map. I could change the latitude and longitude based on the attributes of my element. And I'm actually just using native DOM set attribute here to change the attribute on my element. And again, there's nothing special here that I have to do. And so you can very easily build out a complete application with a handful of web components and a few BackmoveViews. And I think that's kind of cool. We don't have to worry about the implementation details of something like Google Map. We can just have our model pass in a few attributes, and we're good to go. All right, so that's how to consume web components. How can we build them? How can we? It turns out that when we build web components for Backbone, we're building them for everything. So when I say building web components, there's nothing unique here to Backbone. Any best practice you would use to build web components can be used to build any sort of components. So really basic, we might start with a folder for the name of our component. Hello, world. We might throw in an HTML file, a JavaScript file. I have a file here called bower.json, because I'm using Bower to consume my component and allow others to consume it. If I want to put it in a public registry or maybe an internal enterprise registry, this is how I could consume my component and list any dependencies. I don't have to use Bower. Bower is a very popular choice for web components. In my HTML file, I am going to go ahead and put my template tag, using our HTML templates there. And I'll just pass in my script, and I can go to my script. And this is where I put all the logic for my web component. And this is just dubbed out here. But I'll step through it quickly. So I'm going to create my element based on the prototype from HTML element. And then I have four life cycle callbacks. And this is where I can really manage the life cycle of my element. And again, this is nothing really unique to custom elements. These are the same callbacks that native elements are actually going to use. When the browser is going to implement native elements, they're going to use similar callbacks. Created from when my element is created. Attached from when it's added to the DOM. Attribute changed from when an attribute is changed. Detached when it's removed from the DOM. And that's all. And I can do things at that point. I can attach methods here. I can set attributes and work with them. I can do things when attributes are changed. I can fire events. This is the root logic of my component. And then I can go ahead and register the element on the page, pass in the elements prototype. And I'm good to go. The only step next is consuming the element. I can use an HTML import here to pull it in. And then I can use it on the page. I don't have to do anything else. That script is going to run because it's being referenced in my component. And that's about it. And I can go ahead and start using it with backbone. So how does this all fit together? Because we have these two pieces of our application. We have our backbone libraries, our views, our models, our collections, and then we have our custom elements. And I guess how I picture a lot of applications is you have your general application, which is more or less just a collection of these different components. In our normal application, this is usually all backbone. We might have a whole bunch of backbone views. We have our models and collections. Even if this is just the UI layer, it's a whole bunch of backbone views. And that's cool when we use templates and we build it out. But if we want to start consuming some of these web components, what does that look like? I think it means that we start replacing certain things that we might have done purely with backbone views and native elements with our own custom elements or with others' custom elements. And these can live alongside each other. There's no special conversion API that you need. You can wrap your components in backbone views like we just saw, and there's really nothing more that you need to do. And some of these web components might be just vanilla web components that you build or your organization builds. Some of them might be consumed from other libraries like Polymer or X tags or some other third-party component. And that's OK, and you really don't have to worry about the differences there. So what if we took this to its logical conclusion and we just made everything into a web component? People have certainly thought about this. And I think it's a valid consideration, but I'm not sure it's always the most practical thing to do. I think there's still a lot of value from using backbone, things like our application structure, our interface with our server and with our data. And so GitHub actually recently implemented a custom element in production. It's just a simple time element. And one of their engineers in an interview talking about this said they don't see ever going to custom elements for everything. And I agree with him. I think that it makes more sense to use your native functionality where it's available, and then supplement that, extend that native functionality with custom elements. So how do you make this choice? How do you look at your application and decide what should be a component? What should just be part of my backbone app? Where do I draw the line? I don't know if there's a clear line. I think that you have to, as an engineer, look at it and ask yourself a few questions and decide if it makes sense. See if the benefits that you're getting from Web Components outweigh the benefits that you might have from implementing this feature somewhere else. And I think the key questions to ask in terms of components are really, is it component level? Is this really something that's not necessarily unique to your application, but something that could be reused elsewhere? Does it take the place of something in the DOM? I don't know that it makes sense necessarily to go ahead and take purely functional modules and convert them, for example, to custom elements. Should it be sort of portable? And that's portable between applications, maybe, within your organization or between other organizations? Is it context-independent? Can you drop it into a page and expect it to work and not require it to, say, be in the header or footer to work properly? There are certainly API implications to this, but they're also just CSS-style implications. A fixed-width component isn't really helpful if you need to throw it into a responsive design. So keeping those things in mind, even if your context is very specific, if you're making something into a component, you want to kind of remove that logic. And then can your API be represented with the methods that we have for representing an API in custom elements, attributes, methods, and events? And if these come out all true, my checkbox component here, there we go, custom element, and then we can go ahead and make something into a component. And these are just some kind of food for thought in terms of best practices. There are real no best practices yet for web components because they're so new. I think best practices come as a result of actual use. And so I think over time we're going to start to figure this out. But these are just some of my thoughts brainstorming. Keep them small. Do one thing and do it well. Make them extensible. And this means that other people, just like you might extend the native HTML element to create your template or create your custom element. Wouldn't it be great if someone else could extend your element to create their own? Keep them documented. Because the APIs are kind of unique to the components, I think you need to be very clear about how they work. The logic is kind of lockbox, so you want to be very clear about how this is supposed to work. Make sure they're unit tested. I mean, all of these best practices sort of apply to JavaScript code in general. But I think something like unit tested makes a lot of sense for a web component. The reason that is is because things are really easy to test when they're small and have a well-defined API. And so you really get a lot of this for free. Component sort of force you into a very smart interface for your components. I mean, it's very modular. Something that can be easily tested. And so a supplying unit test allows you to kind of self-document your component and make sure that you're not going to break any APIs. Hopefully, you're using some version of your components. That's also part of that. Make sure they're accessible. This is something that on the web is particularly important. If you go ahead and throw a component into your page and it's not keyboard accessible, for example, you're kind of ruining the full accessibility of your application. So maintaining those normal best practices are even more important when you're going to make something that's going to be distributed. And idempotent is another interesting best practice. And I think if we think about how the DOM works, when we put a DOM element on the page, we always expect it to work the same based on the attributes that we pass in. And idempotent method in programming is something that we can call again and again with the same data and expect it to give us the same result. And I think that's true for our custom elements here. Making sure they don't have any other side effects. Making sure they work as expected. Making sure all the effects of your element are contained in its API. All right, so the big question might be, can I use these? The answer is probably not in production. If you have to support Internet Explorer or iPhones. But that's just today. And I think that's all right. Web components are a very new technology. And the specs are actually still being figured out, which is part of the reason that even Firefox is hesitant on putting them into their stable branch. Chrome has had them since this summer when I started playing around with web components quite a while ago, maybe over a year ago now. The specs were very much in flux. And the methods that encode that was written, if you look at web components reposed from GitHub like a year ago, it's very likely it won't work today in modern browsers. So the methods have changed. Some of the API has changed. It's now in Chrome stable, which I think means that the API is stabilizing. And I think we'll see it soon enough. But if we're a little impatient, we have a polyfill. So the web components JS polyfill was built mostly out of the Polymer project. And Polymer originally used it as their platform JS, kind of based polyfill. It's now been taken on as a unique project itself. So not just powered by or built by the Polymer developers, it's kind of built by other engineers involved with X tags and other web components projects, which means that sort of they agreed upon polyfill at this point. And so that will allow you to use web component features in all browsers with some exceptions. The polyfills aren't perfect. Anything worth polyfilling is hard to polyfill. The shadow DOM is particularly tricky. And encapsulation in CSS just doesn't exist. So when you wanna add that feature, you have to kind of have some hacks to support that. And so it's not gonna be completely perfect. Things are still gonna bleed through in certain edge cases. And there may be some performance hits as well. So that's something to keep in mind, especially if you're using this in a production site. So to conclude, we're building some really cool applications in Backbone. And so thinking about the web in the future, I was thinking back to what really excited me about the web in the last few years. And HTML5 was certainly one of those. If you remember, we got all these kind of cool new elements. We got the video element. We got new input elements. We got new semantic elements since like header and footer and nav. And some of those we used, some of them we didn't. Some of them just didn't match up with what we needed in our applications, especially very rich interactive applications. And so what if the next round of components, the next round of elements on the web, came from the other direction? What if they came from the community that built these out and kind of rallied around them? And then we saw these in the browsers going forward. And I think that's part of the promise of web components. And that's what I'm excited about. So thanks. These are really good resources. And yeah.