 Good morning, everybody. I was excited for this 8.30 caffeinated Polymer talk. Me. So fun fact about this title. We came up with it a couple of months ago because for I.O. you have to do everything in advance. And Billions is true. You heard Rahul yesterday in the keynote said that there's over 2 billion users of Chrome now. Every Chrome has a Chrome history or Chrome settings that uses Polymer. So Polymer is on over 2 billion people, which is kind of awesome. But then a week or two ago, somebody tweeted that they had just deployed on every McDonald's menu screen Polymer. So now we're literally serving those Billions. Get it? McDonald's serve. So yeah, let's talk about it. I'm Monica. I'm not Waldorf on Twitter and GitHub and internet places. And I work on Polymer. I work on Polymer Elements usually and building things with Polymer, which is why I really like giving this talk. Because I'm kind of like, you, I'm a user of Polymer. I complain whenever Polymer doesn't do the right thing for me. And there's this quote from Woody Allen that the web is like a shark. It has to constantly move forward or it dies. And Woody Allen, the metro react, we all know this. And he said this, and this is true. We look at the web and it changes every year. We have web components. We have service workers. It's always changing. This is also true of Polymer. Polymer 1 came out three years ago. And it was awesome. But since then, the platform changed a lot. And then the world changed a lot. And we've learned a lot of things from you, users of Polymer, about what you wanted to do. So Polymer 2 also had to change. And what I want to do in this talk is tell you a story about all of the things that came from Polymer 1, all of the things that changed in Polymer 2, and why they actually mean something and why they're useful for you. In Polymer 1, we had this approach of a one-size-fits-all to the library. We went from proof of concept to production. And we basically filled in a lot of gaps that the platform didn't have. We made it so that it was really easy for you to make an element. This is what it looked like. We had this one giant function that wrapped everything, would register your element for you, would create a prototype, would give you behaviors if you wanted inheritance, because you didn't have prototypal inheritance. It gave you declarative listeners. It gave you host attributes. It didn't matter if you wanted all of these things. It gave them to you anyway. And it did work for you to have these things. And it was awesome. And the reason why I had to do this is because two, four years ago, the web component standards were kind of icky. We didn't have a good vendor story. Safari was definitely not into it. Chrome was like, yeah, web components. Firefox was like, sure, we'll do anything. But the spec wasn't really there. We didn't have an agreement on the spec. It wasn't super clean. Some of the things were really messy. We didn't have any best practices. Nobody had made a lot of custom elements. Nobody had to maintain custom elements. We didn't really know what to do. So we made a thing where it was really easy to use web components. And we're like, we'll see how this goes. Which means that the basic use case for a web component was really nice. You could take Polymer out of the box, spend a little bit of time, and bam, you had a button. You had a fancy input. You had anything you wanted. The problem came when you used Polymer for a while and you became this advanced user. And in that case, Polymer didn't really know what to do with it. If you wanted to use it in a really big application, or for example, Chrome Settings only ships it to Chrome. And a lot of the decisions that Polymer or Polymer Elements made were directed at filling in platform gaps. Polymer Elements used to ship a promise polyfill. If you're Chrome Settings and you're only shipping things to Chrome, which definitely has a promise implementation, also shipping a promise polyfill is really annoying. And the problem was that you couldn't take things away from Polymer. And this came because we realized there's very different needs when you're building a library based on who your target is. Your needs are very different if you're building a leaf element, something like an input or a button that sits at the bottom and gets used a lot, versus making a giant view node, like the entry point in your application that aggregates all the things. These are very different elements. You have to think about them very differently, which means the library has to be held very differently in these cases. So if in Polymer 1, we have this one size fits all, everything is an element, is an element, is an element. In Polymer 2, we have this allocart concept. And I hate this allocart because Kevin used it and has an accent on it because I speak French, but they never put the accent on it. So it's really annoying that I have it here. But basically, the idea of Polymer 2 is that you get to pick and choose what you need. If you don't need something, you don't pick it. You don't bring it in your application. So as part of the Polymer 2 release, we did three things. We updated Polymer 2's the V1 specs, which are awesome, have V6 classes, they're delightful. We removed all the weird abstractions from Polymer 1. If you've ever used Polymer 1, all those Polymer DOM calls that were there because we had to hack around the platform, you don't need them anymore because the platform's here. And we also try to do this in a minimally breaking way. And this was really important to us because the cleansing wave of fire of updating your application whenever a library changes is really frustrating for everyone. So we wanted for the change from one to two to be really smooth. And again, this is why it helps that I work on elements and not core because Kevin and Steve would update the library and be like, we made these changes. And I'd be like, you broke my input and I have to use like 17 hours to fix it and we're not going to do that because nobody's going to want to do that. But what I want to focus on today is these actual new changes that are in Polymer 2 that came from the V1 specs, but all of the awesome modularizing feature breaking that we did. The reason why we got to do this and the reason why we were able to modularize Polymer 2 is because the platform caught up, the web component standard is really awesome now. It works everywhere, Safari has a custom element in Shadow DOM implementation, never thought I'd see the day. But it's here and we have an awesome cross vendor story, which means as a library, we can now take a step back and like focus on how to actually help you solve problems, not on just like filling gaps and like writing polyfills until the end of time. Which means now you get to use the platform, you can make web components, you don't even need Polymer, but if you want to use Polymer, we're there to like empower you, to help you, to like solve all of the really annoying problems that you might have and all the boilerplate that you might not want to write. One of the things that we used to tell you in Polymer, I said this so many times last year, I don't think I can even remember, is do less be lazy. In order to make your application fast, you had to use less of Polymer. You couldn't like give back features of Polymer, you just had to like be very careful about using them. And we didn't want to make this mistake again in Polymer too. So in Polymer 2, we have like an opposite, very positive approach, which is do more if you need to. When you start with a custom element, you start from the bare metal, you get HTML element, you get nothing. If you need some sugaring or if you need like declarative getters from Polymer, then you can subscribe and be like, hey Polymer, help me with this thing. Don't give me everything else, I didn't ask you for data binding, just give me the one thing that I ask you for. And that's exactly the entire methodology around Polymer 2 and why I think it's really awesome. And the reason why this works is because we now have options. We split Polymer into like these individual mix-ins and these options that you can basically subscribe to. So when we start off with an element, I'm sorry this is at the bottom, you start off with HTML element. So this comes from the spec, this is the platform, it's just whatever you extend to make a custom element. And then on top of it, you might want help with something. You might want help, for example, with declarative getters and setters. I personally don't like writing getters and setters and keeping all my attributes and properties in sync. It drives me absolutely insane. On top of that, you might want help with stamping your template. Templates are really nice and I'll tell you all about it in a little bit. But if you got used to Polymer 1 templates, Polymer 2 also has templates in the same way. Data binding is a thing that you really don't want to roll on your own. It's really nice if a library helps you with that. And that's another feature that we can help with. And finally, all the declarative goodness that you're used to from Polymer 1, like declarative listeners or like synced properties and stuff like that, these are all features that you might want help and you would expect help from a library like Polymer. The really awesome thing about this graph is first of all, it's a rainbow. And second of all, it corresponds to exactly the mixes that we have in Polymer. So the getters and setters come from something called property accessors. And then the template comes from template stamp. It stamps the template. It's the best-named thing I've ever seen. And it goes all the way to the top to Polymer element, which has pretty much everything that you are used to from Polymer 1. The other awesome thing is that because they're individually split, you get to control the size of Polymer that you include in your application. If you know you're not gonna need data binding and you're not gonna need to stamp your template or anything, you can just take a 2.2K hit that's smaller than your header image in your application. So that's pretty much fine. Even Polymer element that has all of the things is just 11K. It's really small. So what I wanna do in this talk, and I think it's like, I'm really sorry it's at 8.30 because there's gonna be a lot of code, but I wanna tell you exactly how you would use each of these mixins because I think that's really important because that's the whole power of Polymer 2. And I'm gonna do this with a fairly contrived example. So I have a button, and every time I click it, you get a balloon, and that balloon is obviously an emoji because nobody has an image of a balloon lying around that Legal will approve to use in this talk. And I have two attributes on it. I have a limit and I have a counter. I want the counter to be reflected. So when I say reflected, I mean that if I update the property, the attribute is in sync and gets updated as well. I don't want the limit to be reflected. So when it boots up, I start up with a limit or not, but then if I update the property, the code considers this new value, but it's not gonna get reflected as an attribute. You may do this for performance reasons. This is how a lot of the actual HTML elements work. So like the native input element has a lot of properties that's not actually reflecting. So even though this is a contrived example, I thought it was like a sort of similar as this thing that you might do in real life. So that's our element. All of the code that I'm gonna talk about so that you don't like take furious notes or anything is at this URL. So Glitch is this awesome new thing that the lovely people from Fog Creek put together. It's basically like a JS bin on steroids is a new developer environment where you have like a client and a server. They give you like an express server and you can have node modules and stuff. And it's really useful for demos like this. And the other awesome thing is that it generates a random name for a project, whatever, but my random name was aspiring chauffeur, which I thought was really appropriate because it's like driving you around on your Polymer 2 experience. So that's the link. Go to it and have fun with it. You can like clone it and remix it and whatever. Okay, let's get this going. We're starting with HTML element. We're gonna make a custom element with vanilla JavaScript, no Polymer at all. There's two parts of making a custom element. We have to like define a prototype, which is what the element does. And then we have to tell the browser to associate a tag without prototype. And that's what the custom elements dot define line does. Basically says, hey browser, whenever you see my element, I really mean this actual thing. And then the next thing that the platform gives you is a bunch of life cycle methods, which are basically callbacks whenever your element does something interesting. You get a constructor when you mute it. You get something called a connected callback and a disconnected callback. And these are whenever you attach an element, we append it to the document or you remove it. And then you get this awesome attribute call, change callback. So whenever you change one of those attributes in the markup, you get this callback. And the way this works is that you subscribe to a list of attributes you care about. So something like counter and limit would be here. The reason why you have this list is because you don't want to react to every single attribute that changes. So you specify the ones you care about. Cool. So here we go. This is most of the code in that element. There's like another get it and set it. Don't panic, we're going to go through every line. We know it's a lot of code. So the first thing we're going to need to do is create a shadow root so we can put our styles and encapsulate them. That would be really awesome. And you can do this in the constructor. You can do this in the connected callback. You can do whatever you want. In the connected callback is where I do my rendering code. And here, this render function is basically a giant boring function where I create DOM and styles in JavaScript. You could have a style node and append it here. I chose to do this because I was lazy and terrible. This is not the greatest way to do it. But it's fine because we're going to use templates anyway. And what this is doing is just creating a button, having a click handler on it, that increment function basically just adds one to the counter until it hits the limit if there's a limit. It styles the button, whatever. It's just like normal DOM creation. Once you're done with that, we have the attribute change callback. And here, there's like an interesting philosophical problem you can pick a camp to live in. There's two ways you can do this. You can have properties or attributes be the source of truth. If you have attributes be the source of truth, you would do all of your work in here and just like customarily update the property just to keep it in sync. I prefer to keep my properties be the source of truth, so all I'm doing here is just updating the property and doing all the work in my setter. And the reason for that is, again, I don't want all of my attributes to be reflected. So if I did all the work here, that means all of my properties were reflected and that's kind of lame. It's also slower. Setting an attribute is not free. It's actually quite expensive. And finally, if you have properties be the source of truth, they get to have types. Your integer can actually be to the integer and not to the string, so when you add one to it, you don't get 21 balloons like I did the first time I made that element. So here's our setter. And as I promised, I'm gonna reflect that attribute if I want to. And then I'm gonna call display. And this is, take a moment here because this is the first deliberate piece of code that I actually wrote. Because up until now, it was mostly just like gluing things together and boilerplate and my render function. But what I'm gonna do in display is just take my counter and basically repeat an emoji balloon all the time. And this is why images suck in emoji rules because you can just inner HTML it, yay, or text content it if you want. I like to enable cross-scripting errors here. Cool, so that's it. That's my code. I have a display function, it gets updated. We didn't need a library to do this. This is a small element, but it was still a lot of boilerplate code. Imagine if your element is enormous and you have to do this for like 17 properties you might have, that gets a little bit messy. So this is where Polymer can help you. So let's do this again, the same element, but with less of the spoiler plate. And the first thing we're gonna use is property accessors. Remember, property accessors gets you basically getters and setters. They access your properties, get it? I just figured that one out right now. I've been using it for months, great. Never asked. So this is the code that we left off with. This is what we had. And now I'm just gonna like, mangle it and make it better. The first thing I'm gonna do is rather than extending HTML element as before, I'm gonna extend property accessors and it builds on top of HTML element. It's a mix-in, it's a hardware order function, goodness, JavaScript. The next thing I'm gonna do is call this enable properties function. So this is the little bit of boilerplate that turns on your accessors. And the awesome part about it is that you get to control when exactly you're gonna turn them on. So we tend to do it in connected callback because that's after all of your attributes have booted up and attribute change callback has been called for your initial state. So basically in connected callback, you're now ready. Your element has booted up with its initial attributes and you're like, sweet. Now make me getters and setters and properties for them. And then as a result, you also get this new callback called ready, which comes after connected callback and after enabled properties has been called. So after all of your properties have been set. And this is where I can now do my rendering. So I can actually boot up with my initial state with properties, it's awesome. All of this code about observed attributes and all my getters and setters can now go away because that's the work that Polymer is doing for me now. And I'm gonna replace it when a thing called properties changed. So much like attributes changed, this is properties changed. The difference is that this is a batched call. So if you set like three properties in a row, you're not gonna get three callbacks. You're gonna get one callback that says, hey buddy, you set three properties, do you wanna deal with this? Which is awesome because if you're just gonna call display over and over again, if I update both the limit and the counter, you don't wanna call it twice. You just get one batched callback. And here you can see that I'm gonna explicitly just reflect the counter attribute but not all my other properties that I may get a callback for. Awesome, we've already cut the code in half. We're doing great work and we've just added 2.2Ks to it. Awesome. We have one more line of code which is a static function on your class that basically says, Polymer, please pay attention to this class and every time I have an attribute, make a property getter and setter for it. So that's awesome. A lot of the sugaring that comes from Polymer until you hit Polymer element is on static functions on your class because that basically what it does. It has to like, notice me, notice me, pay attention to me. Which is great. So that was property accessors. Remember, we got properties and attributes being set in sync and free getters and setters. The next thing we get is template stamp because if you remember my render function was really horrible and you don't actually know what this looks like. It's a pile of DOM and a pile of CSS. Maybe it's good, maybe it's not. It's unclear. But what I really wanna replace it with is a template. Templates are awesome. We use them in Polymer 1. Templates are the fastest way to stamp static DOM. We really like them. Also, your editor understands them and displays them as HTML and CSS so you can actually be like, oh yeah, I see the button. It's got a style. And in this, the template is identical to what I had before. So the host, it's the same styles. My buttons are the same styles. I literally just copied it into a template. I didn't do anything else. The other awesome thing about using template stamp in Polymer is that you get declarative event handlers. So now rather than, I could add an event listener to my button, button.addEventListener, a function, and bind it. But why not let somebody help me with this? And this is an awesome way to be helped with. And much like in Polymer 1, template stamp also gives you items of interest. It's this idea that if you put an ID on something in your shadow DOM, Polymer will just cache that ID so you can access it by this.dollar.output. Again, you could do this too. You could query select for it and put it somewhere in your class so that you don't query select every time you need it. But this is an extra layer of sugaring that is really useful. And we found people really liked. Sweet, now that we have this template, we can cut off more code. My entire goal in this talk is to start with a bunch of code and leave you with nothing at the end. This is how that's gonna progress. So this is where we left off. The first thing we're gonna do is gonna update this extension. So we're now gonna extend template stamp, which uses property accessors, which uses a shim element. It's turtles all the way down. And then I'm gonna cut off everything that had to do with rendering because, again, I'm not doing this rendering by hand anymore. Template stamp is gonna do it for me. So I'm gonna delete it and then I'm going to replace it with, if I can get this click going. In my ready callback, which remember I had from before, I'm gonna append my DOM. So I'm basically gonna get the template from somewhere in my document and you can use your favorite way to do this. And then I'm gonna create my shadow rights and append my template. And this is gonna create this dot dollar and everything for me in ready. And that's it. That's all that I have to do for a template stamp. So now I got to take away that render function and take away the awful part about it and convert it into a template. Yes. The next thing, and this is my favorite part of Polymart, is property effects, which gives you data binding. And data binding is my favorite because everything just like magically gets kept in sync and properties get updated without me having to call this dot, this dot, this dot all the time. So this is our old code. And now I've started like hiding code away from you that doesn't matter to make you feel less scared at 8.30 in the morning. So I'm now going to extend property effects. And now here you can see that like it's no longer turtles all the way down because property effects requires template stamp and everything below it. So it's just going to do all of the turtles for you. But property effects also builds on HTML element is still a mix in. And I'm going to get rid of my properties changed. Remember the only reason why I had this properties changed is because I wanted to keep my attributes and my properties in sync. And also I needed to call that display function that like reached into my DOM and was like, you need to put balloons, needs more balloons. But if I have data binding, I don't need to do this by hand. That's the whole point of having data binding. So I'm going to remove that function. I'm going to again call a static method on my class which is going to do that reflection for me. So now we have this create reflected property call that says if you see a property called counter also make sure it's an attribute and keep these in sync. So I don't have to do that anymore. And now if you go back to my template to actually use the data binding, we use the display method as before to like reach into output and update it. So what I'm going to do instead is use data binding inside of output which is going to call the display function every time my counter property gets updated and then my display function is really easy. It just says, you know, number of balloons I care about. That's it. This is awesome. We're like most of the way there. The only other thing we still need is, you know, sugar and spice and everything nice, declarative properties and property observers, all that like nice syntax that you're used to from Polymer One if that's a thing that you want to use. So this is the code where we left off. And look how, before we even go to it, look how like clean and straightforward this looks. I have a constructor, my element is booting up. I have a connected callback. It's when something gets attached. Ready is when all my properties have been set. I care about some observed attributes and I literally have code to make this element work which are the display and increment functions. Nothing about this looks in anyway like boilerplated or weird, but we can still do better. So I'm gonna extend Polymer Elements now and this is like a new kind of custom element that I can extend. And I'm gonna delete basically everything that was not code that I deliberately wrote. All I really wanted this element to do was to display balloons and increment every time I press that button. So that's what I expect that element to do. So I'm gonna cut away all this boilerplate and then replace it with this properties object that looks very similar to what you're used to from Polymer One. I have a bunch of properties. I have a counter property. It's a type number so I can add one to it really safely. It's reflected to an attribute. It starts off at zero. I have a limit property. It's just a number. Don't really care about anything else. And that's it. This was code that I wanted to write, add. The next thing I have to do is put a little bit of glue for automatic template finding because if you still remember in that ready function I still had to like find the right template that I wanted to stamp and I really just want Polymer to automatically do this for me. And this is what the static getter does. It says, look for the template called like that belongs to my element tag. And the way this works is by wrapping everything in a DOM module. And this is why it looks exactly like Polymer One. DOM module is a custom element. It has a template. It has the definition of the element and it's gonna glue that template to the element that's being defined. Kind of like in an awesome taco. In the Polymer team we usually call this like, it looks like a taco because your DOM module is like the tortilla and then you put all the goodness in it like the meat and the cheese and not the cilantro. I'm one of those people allergic to cilantro. Cilantro is awful, which is why I want to show you this awful emoji that is like 90% cilantro. I want to find the designer at Apple who is like, I've seen a taco before. It has cilantro and apparently onions. That's a, they're like in California. There's tacos everywhere. I don't understand. So that's it. That was our code. So I just want to go through all the five things again so that you know them. HTML element is off the beginning. Property accessors are how you get, you know, getters and setters and keeping your properties and attributes in sync. Template stamp lets you, you know, use templates for stamping rather than awful CSS and JavaScript or other awful situations you might find yourself in. Property effect is gonna give you data binding and Polymer element gives you the properties block and declarative observers and listeners and the things that you use to from Polymer one. And the reason why I'm really excited about this and the code that I showed you is that I feel that with Polymer two, we're actually, it's, I've been saying this in Polymer one two but I think it's actually becoming true in Polymer two that Polymer is kind of like jQuery for web components and not in the sense that you don't use it anymore and you have four copies of it that you haven't forgotten or you haven't remembered in your site but in the sense that like it actually helps you write things really easily. When jQuery came out, DOM manipulations were hard. Writing things that worked on IE and Safari and was there even a Safari and Chrome were hard and jQuery helped you with that. You got to write the same line of code and it worked the same way everywhere and Polymer does that for you rather than like letting you write all this boilerplate if you wanna use a library, you can do it and it's gonna do all the heavy lifting for you. It's not gonna make decisions for you. It's just gonna help you do whatever you already wanted to do. And the way this works is because E6 classes are amazing and this is the thing that we didn't use to have in Polymer one. E6 classes code looks like platform code. It doesn't look like weird frameworky code that you had to do so that your framework works. It's just what the platform wants you to do. Look at this code that we, this is the last bit of code that we left off with. I have a class. It extends something. That's inheritance. That makes sense. I have some getters or like some static getters and setters. Object, they have some JavaScript. It's just a normal class. It uses Polymer, but it just looks like normal code. And the awesome thing about inheritance, everyone, is that we actually get element inheritance now, which is the thing that I've been asking for years. So this is, if you want to extend from this element, all you have to do is just update what you're extending. So I can now have a child element that extends from this element that we've been working on for 90 slides. And it can update because it's extending it. It can update anything. So maybe I don't want to show balloons every time. Maybe I want to show cats in three times as many because obviously I want more cats than balloons. And that's really easy because it's just a normal class extension. I'm just going to update what that display function does and be like this particular child is just going to display a lot of cats. And I can do the same thing with a template. I can have the child have a specific template and you can override the template function that Polymer uses to display your template and be like, listen, Polymer, you take whatever template my parent had and shove my template at the end or in the middle or wherever placeholder is. You control these things. And this is really awesome because I think these are ways in which Polymer really helps elements in particular with inheritance. But remember we had like these different kinds of elements that we had to think about because everybody has different needs. And I think at the bottom, something like a leaf node would be paper checkbox. Paper checkbox in Polymer 1 lived in a really hard space because it had to be very performant. This is the Chrome settings page. And in Chrome settings, they try to use paper checkbox, sorry, Chrome history, actually. And basically for every item of history, paginated or not, you had a checkbox. Maybe you're showing 100 checkboxes. No matter how fast paper checkbox was, it still wasn't fast enough to actually render and not to like cross the page extra seconds. So we couldn't make paper checkbox fast at the time because people also wanted like 17,000 features from paper checkbox, such as making it a tri-state so you can use it in trees, being able to style the label, being able to control where the label goes around the checkbox. I'm not making these up. These are real features that people asked for. And it was very hard because we didn't have enough control to both make it extremely fast for one use case and extremely featureful for another. But the amazing part about Polymer 2 is that now we get to control this. Paper checkbox can be one of these vanilla custom elements. It needs to be super fast. It doesn't have any data binding. It just has one bit of CSS. Maybe it needs property accessors, but it probably doesn't even need template stamp. It can be incredibly cheap and incredibly fast. And if you want to add features to it, you can inherit from it or you can just add features to it later. But paper checkbox by itself can be super fast now. A different element, paper input, is still one of these leaf elements, but it's really complicated and really expensive. It has to do everything the native input is, which is 21 different things for the record. And it also has to look pretty because the input element is hideous. So it gets to use more of the sugaring that Polymer can provide. But on top of that, we have something like gold credit card input. And for the record, I had to blur that visa icon because you're not allowed to show the visa icon without asking for permission. Thank you, lawyer cats. But so gold CC input looks exactly like that paper input, right? Let's go back to it and let's go forward to it. Yeah, it looks exactly the same. It's just basically paper input with an extra icon and a validation of your credit cards. The problem is in Polymer 1, we didn't have inheritance, so it's literally all of paper input copy pasted into a different element. Do you think gold CC input has all the fixes that have been going on for the last year in paper input? No, it doesn't. It's really broken. This is where inheritance helps. So in Polymer 2, we can now update this horrific element and be like, listen, you're really just a paper input with these two very trivial changes. And this is gonna be amazing. It's gonna make maintenance awesome. It's gonna make these elements actually be loved again. I hate them so much. I had to copy paste so much going. But yeah, this is how it helps elements. This is really great. And the final last kind of element that we were talking about is this thing that sits at the top of your application and has to just aggregate a whole bunch of things. This is a bunch of elements from our shop app. And news article is basically like the article that you're looking at. And it depends on like a whole bunch of things, the category that you're looking at, the page that you're on, the route that you've been set on. And you could set all of these properties by hand. You could have a listener every time like the route changes. You can go and like do news list dot list equals something, news article dot category equals something. You could, but you don't have to. That's why data binding is amazing. That's why Polymer is really good at this. So this would be the kind of element that you would probably only have like one of them in your application or a couple. So you could throw the kitchen sink at it, use all of Polymer. This would be totally fine and it'd be awesome. So these are the ways in which Polymer helps elements. But Polymer also helps apps because this is the other kind of target audience we care about. And we listened a lot to people who are using elements in their applications and were like what are the biggest problems that you have? So shadow styling and styling encapsulation is amazing. It's really, really awesome if you're making one of these leaf elements that you want everybody to reuse in your applications and not accidentally stomp on their styles. That's a whole point of it. It's a little bit hard if you're starting with this like monolithic application that has like random CSS and 17 different CSS files and you're like I'm gonna go gung-ho on web components. And you might have a problem with that because styling encapsulation is gonna go a little bit in the way. If that's a problem that you have with, Polymer 2 helps with it because again, everything is just a JavaScript class. You can just override and extend things that are in the way. So this is what the normal attach DOM function from Polymer element is. It creates your shadow root and puts content in it. If that's not a thing you want, just override it and say just put my dominant and it's gonna be fine. And this is great. Another thing that we've heard that people might want is define your elements just in script and not depend on templates. And again, this is super easy. You have a template function, a template getter that Polymer element uses, just replace it with, rather than fetching the template for you automatically, replace it with a string or however you're stamping your templates normally. That's a thing that Polymer can help with it. And all of this works because ESX classes are finally, like they're amazing and we can use them and they're here. This is what the platform always wanted us to do. Yogi Berra, the inventor of functional programming, once said that when you come to a fork in the road, take it. And I think this fork in the road is web components. They're here and they're awesome and they've given you this promise that how you build an element doesn't matter. You can use vanilla JavaScript, you can use Polymer and I think it's really awesome and I really hope that you take this fork with us and start using web components. Also Polymer too, yay, thanks.