 So thank you all so much for coming out and sitting through that Miami Vice opening credit sequence. That was fun. So yeah, my name is Rob Dodson. I am a developer advocate here at the Googles and work a lot on web components, work a lot on Polymer. And today I just want to talk a little bit about some of the goals behind Polymer 2.0. And from there I think we can then dive into like how Polymer 2.0 actually works under the hood. So as Taylor said in his talk, really the primary goal Polymer 2.0 is to bring developers closer to the platform. And so what we mean by that is that web components are just this massive, awesome, powerful set of specifications that are being implemented in the browsers and shipping natively today. And so that means that your users don't have to download the code to make that machinery run. It's just built in. It's already there in the browser. And so we think of web components as this really massive thing. And we think of Polymer as kind of like a smaller piece, just sort of orbiting all of that. When we tell developers we want them to use the platform, we really want them to use web components as much as possible and feel like they're using the native APIs, and then use Polymer to sort of like augment things where they need to, where they want a little bit of a productivity boost. I like to say that Polymer is just sort of an opinionated usage of the web component standards. It is by no means the only way to do web components. There are other libraries out there that use web components. And they use them completely differently from Polymer. And I think it's really important to note that. That web components are a very flexible set of primitives. So Polymer is not the only way to do web components. It's just a way to do web components. And it's one that we've come up with which we feel like helps developers leverage as much of that good built-in platform as possible. So one of our primary goals, aside from getting people to use the platform more, is to do less magic, right, to remove things like Polymer DOM, these sort of weird, leaky abstractions, to simplify our data binding system, and ultimately just to bring the syntax of using custom elements much closer to just like the native API. And finally, we want to make sure that we're bringing the library size down. We want to make sure that Polymer gets smaller as time progresses. And so that means shedding abstractions, using more of what's built in the platform. And ultimately, I think that the way we achieve all of these goals is just by doing less. And so if you look at the web component standards, in general, when you're working with them in Polymer, we don't actually sugar most of these APIs. We don't try and sugar the way that Shadow DOM or HTML imports works. We are just using them directly, natively. The one exception to this, though, is custom elements. And I feel like custom elements is the area where most of Polymer's features are directed. So these are going to be the main focus of my talk, because I really think you need to understand how custom elements work in order to understand really what Polymer 2.0 brings to the table and how it's evolved from Polymer 1.0. So let's talk about the DOM for a second. Because to understand custom elements, you really got to understand the DOM. Every time that you're writing HTML, you're just writing some markup, what you're actually doing is creating instances of classes. So every HTML element inherits from a base class that implements the HTML element interface. And then these subclasses get additional properties and methods that they expose on their own interfaces. So for instance, when the parser sees an input tag in your markup, it says, oh, I see an input here. I'm going to create an object that implements the HTML input element interface. And that object has unique properties and methods. It can do things with validation and with autocomplete. The same is true when it sees an image element. It's going to create an object that implements the HTML image element interface. And that has a source property. It can go out and fetch things for you. Even a div, which is just kind of a boring tag. It doesn't really do anything that interesting. Even it has its own interface that it implements. Now let's say you're trying to do something like this. So you're trying to build your own kind of widget. So the parser is going to see this thing. And it's going to be like, uh, I don't know. This looks like div to me. So it's just going to create a div element with some image elements inside of it. So at this point, what do we do as developers? It's like, well, I really want this thing to be a carousel. I'm trying to build this kind of specific widget. So I'm going to bolt on some JavaScript. And I might turn it into a jQuery plug-in or something like that. I might use vanilla JavaScript. Pass the element to a constructor. And that constructor is going to wrap kind of like a JavaScript membrane around those tags and kind of like control them. But really what you're doing is you're just taking a div and you're glomming some JavaScript onto it and kind of acting like it's puppet master. You're trying to make it seem like it's a carousel, even though under the hood, we know it's really just a div and some image elements. And so when you think about it, this is kind of a weird way to program. Because as I said earlier, you've got this whole parser behavior, where the parser sees an input tag and it creates an input element class. There's this whole system, and we as developers can't actually take part in that. That means that we've got to make these weird JavaScript wrappers. And that's just really how it's always been done on the web. We've never really had a way to say to the parser, look, when you see this input tag, or sorry, this carousel tag down here, create an instance of this MyCarousel class, the class that I am defining now, and associate it with that tag. And so fundamentally, this is what custom elements changes. This is what custom elements give you, just the ability to associate a tag with a class and partake in that really cool parser behavior. So it's a very simple, primitive, but it's also very, very powerful, and it's very flexible what you can do with it. Now recently, as Taylor mentioned, custom elements have moved from the v0 specifications over to the v1 specs. And so the changes in the v1 specs were made so that we could get all the browsers on board with the final look and feel of custom elements. And now that all the browsers are happy and everyone is either shipping them already or actively working on implementing custom elements, it's time for Polymer to evolve and take advantage of these specs as well. So that's what I'm going to be focusing on for the rest of this talk. I want to talk about how you create v1 custom elements just using vanilla JavaScript. Then as I'm doing that, I'm going to highlight some of the pain points that you're going to encounter just writing your own custom elements. And lastly, that's going to help us illustrate what Polymer 2 gives you and how it can make you just more productive. So let's look at the anatomy of a v1 custom element. So start off when you create any custom element. The first thing you do is you create a class that extends from HTML element. And then you call window.customElements.define. You pass it your tag name and that class that you want to associate it with. So from here on out, you're telling the parser, hey, anytime you see that tag, create an instance of this class. Once it's created that instance for you, it's going to start triggering the lifecycle callbacks on it. The first lifecycle callback that it calls for your element is going to be the constructor. So in v0 custom elements, this was the created callback. In v1, it's now just a regular ES6 class constructor, which I feel like this is more in line with the way that classes just work in general. So I prefer that we've moved to this naming. The first thing you want to do inside of your constructor is you always want to call super. This is especially important if your custom element extends another custom element, which we'll talk about a little bit later. And then the constructor is also a great place to do things like set up your event listeners, create some initial state, and attach a shadow root if you want. But what you cannot do inside of your constructor is you cannot go inspecting attributes or inspecting your children or doing anything like that. You really don't want to be poking the DOM at all inside of your constructor. This is actually a requirement of the v1 specs. I think it'll throw if you actually do go poking at children. And this is because they might not have upgraded yet. So you want to defer that work to the connected callback. This is going to be called every time your element is inserted into the DOM. So this is a really good place to go out and fetch resources if you need them to render some initial UI. There's also a disconnected callback. This is going to be where you get your cleanup work. There's a new adopted callback, which every time your element gets moved to a new document. I'm assuming most of you will never use this. But I did want to include it just for completeness sake. So if you're computing something based on the URL, you get moved to a new document, you might want to do something in this callback, but probably won't use that often. And finally, there's the attribute change callback. And this one is pretty important. So this is run anytime an attribute on your element is changed in some way. So it's like a very convenient mutation observer. And in Custom Elements B0, this would run for any attribute change, which could actually be kind of noisy. So in Custom Elements B1, you now have to explicitly tell the browser which attributes you would like to observe. So you do that by placing those attributes in an observed attributes array. So up here, I've got this selected attribute that I've put in my observed attributes array. And that is the only attribute that's going to be able to trigger my attribute change callback. Now, a useful thing to do with the attribute change callback is to use it to synchronize your attributes and properties. So I usually do this by defining a setter and getter pair on my class. So let's say I'm observing a selected attribute here. And I tell my attribute change callback, hey, anytime that attribute changes, call a setter with the corresponding attribute name, pass it that incoming value. And then I'm going to define set and get functions on my class. Now, if you're not used to writing ES6 classes, a setter and a getter, these are functions that are going to run anytime someone tries to assign to the property or tries to retrieve the value from the property. So inside my setter, what I typically do is I do a little dirty check to see if the values are different. If they are, I will save that value in sort of like a stored private variable. And then I may also reflect the change back to my element itself by setting its attributes in the DOM. You don't have to do that. That's optional. But you might do that if someone is setting the property in JavaScript, and you want to reflect that back to the DOM, maybe for styling or something like that. And inside the getter, I'm just going to return the selected value that I've stored. Pretty easy. Now, a bit of personal style is something I like to do. You don't have to do this. This is something I like to do. By the way, that's supposed to be an ice cube wearing sunglasses. I asked my teammate Monica what she thought that was, and she said ham. So that is not ham. I'm not trying to be as, I mean, ham is cool and everything. But I'm not trying to be as cool as ham. But anyway, something that I like to do, I've been inspired by the whole sort of unidirectional data flow movement. I think it's pretty interesting. So what I like to do is I like to make sure that all the state from my element can be defined entirely by its properties. I think that you should be able to describe your element at any point in time based on its properties. So for instance, doing something like this should work, and you should be able to basically achieve any functionality and any rendered state or any rendered UI of your component using an approach like this, where you're just setting properties. So this way properties become the source of truth for your element. This means I also try to avoid methods that change my element's state, especially if they don't reflect that back to properties. The reason is because I feel like these methods tend to duplicate functionality that can already get out of my properties and out of my setter functions. And also because having a bunch of methods on your element can oftentimes require a bunch of imperative setup steps in order to get it to a particular state. And that can be very difficult to replicate if you're using your element inside of a framework, something like React, for instance. So for example, if you're building a dialogue, it could be tempting to say, OK, the only way that you can open this dialogue is with this open method. That's the only way you can get the thing to open. And I would say, don't do that. I would say, instead, give it an opened property and have the underlying setter for that property handle rendering the new UI for the dialogue. Again, I think that this simplifies your code. You don't end up with weird methods called Toggle, who's sole jobs just to toggle properties back and forth. I've totally written a checkbox with a toggle method and realized, I can just get rid of this and just use a check property. And it also makes it so your element can play nicer with those top-down unidirectional data flow frameworks. Again, that's just personal style. That's something that I like to do. You absolutely do not have to listen to me. But it's just something I want to do, including this talk, because I think it's perhaps a good and useful approach. Now, before I went off on that whole tangent, I was talking about keeping attributes and properties in sync using that attribute change callback. And looking at the code for all of this, you might think, OK, that's cool and all. But that's actually like a lot of code just for keeping one attribute and property in sync. It's going to be a lot of work to do that if I have many, many, many properties on my element. And so this is an area where I feel like we've hit a bit of a pain point in a place where perhaps we could add a good abstraction to help us out and make us more productive. I want to continue on the subject of data flow, because I've already sort of broached it. For any custom element, we like to say, you get data in using attributes and properties. To get data out, you're going to use regular DOM events. So if I were building a custom checkbox, I might start off by extending HTML element in my class. In my connected callback, I could add an event listener for the click event and have an on-click handler. Inside of that handler, I might set the checked property. Maybe I've got a setter somewhere that's going to update my UI. And then I'm going to just dispatch a custom event that contains the state for my checked value. Pay attention to this, because this is also how you dispatch events in Polymer 2.0. So in Polymer 1, we had this thing called fire, this dot fire that you use to dispatch events. And as I said earlier, we want to remove abstractions where we don't need them, where the platform is already providing something that totally works. So in Polymer 2, we got rid of this dot fire. You're going to use the regular dispatch event, because that's the platform. And we should leverage it as much as possible. Another bit of cool ham personal style here. I like to dispatch events for every state change, for any sort of property or anything like that. And again, the reason is because I think it lets unidirectional frameworks revert that change if it does not match their own internal model. So we can just dovetail into those systems a bit easier. So for instance, the way that a library-like React works with a native checkbox is it listens for its change event. If that does not match its internal model, it'll revert that change on the checkbox. So I want to make sure if I'm building a checkbox, that same system will work. Again, personal style, that's just how I do things you absolutely don't have to listen to me there, but that's just something I think could be helpful. Now, OK, data goes in via attributes and properties. Data is coming out via events. There is a slight mismatch here, though, particularly around attributes and properties, specifically attributes. Properties, right, we can use those to pass any value we want to an element. So we can imperatively assign to an element an array or an object or even a function, right? But attributes, we can only pass string values, OK? And so this can become a bit of an issue for folks, depending on how you're constructing your elements. If all you're building are leaf elements, like simple UI components, like a button or a dropdown or something like that, this is probably fine and it's not a big deal, OK? If you think about most of the HTML elements that you use every day, they're essentially all leaf elements and you can figure them just with strings and their attributes. So for example, if I'm going to drop down element myself, that it's selected attribute is a string, that's fine, no big deal, that's how HTML works. Another option is if I need to give it data, it could also perhaps come through the children. So the video element has source elements as children, so you can pass it multiple sources and it'll figure out based on the environment it's in, which of those sources to use. And so you can maybe do the same thing with a leaf element. But this is a problem if you're trying to build your entire application out of custom elements, that there's basically, there's no declarative way to pass complex data in HTML. So this feels like potentially another pain point. This is something where we could use an abstraction to make this more productive for us. And kind of like a meta point, because I've had conversations with people on Twitter about this, I don't think that this is something that custom elements or web components needs to solve. I think custom elements has a very discreet responsibility to associate a tag with a class. But I do feel like this is maybe a sort of a separate missing feature in the platform. It's something that I would be really, really interested to see if we could ever possibly standardize or turn into something that everyone could do. But today we have abstractions. We have libraries that work around this. So yeah, anyway, I'll get off my set box on that. The last thing I want to talk about is rendering. So I've got my custom element set up. How do I render some of its UI? So let's say I'm building a simple clock element. And inside of this thing, I've just got a template here that I'm assigning using inner HTML. And inner HTML can be a little weird. It can be a little gross. So maybe a nicer thing to do would be to go fetch a template element that already has some DOM in it, clone that, and extract that into my element. And I could stamp that into the light DOM, or I could pop it in the shadow DOM, either way. I'm going to switch back to this inner HTML example just so you can see what I'm trying to work on. Now again, I'm building a clock. So really the only thing I want to do is put some text in that span. I want to put the current time in that span. That's sort of the whole focus of this element. And so to do that, I'll define a setter for my time value. And then look at the code inside of that setter. So what I'm doing is I'm querying for that span, and I'm setting its text content property to whatever the new value is that just came in, whatever the new time is. As you can imagine, with a large element, a lot of DOM, a lot of setters, a lot of properties, that could become very tedious and very repetitive. We can end up with a lot of boilerplate in our element. We're just sort of repeating ourselves, we're querying the DOM, we're updating the DOM all over the place. So to me, this feels like another pain point and possibly another good place to add an abstraction. So we used custom elements. We did some cool stuff, but we also hit upon some pain points. And it's because custom elements are a purposefully low-level API. They're not trying to solve everything for us. And so there are some places where things could get a little tedious, and we might need to add an abstraction. So let's look at how we can use Polymer 2.0 to solve some of those issues. Again, a big goal of Polymer 2.0 is to make developers feel like they're using the platform as much as possible, to bring them as close to the platform as possible. And so that means removing magic, and making it really clear that you're basically, most of the time, just interacting with native APIs. So where I was originally extending HTML element when I created this class, now I'm going to extend Polymer element. OK, so what's Polymer element? What is inside that thing? Well, Polymer element really is just a collection of mixins that extend and add functionality to HTML element. And so if you want to actually even deconstruct it a little bit, let's say I just want to use one feature of Polymer. I don't want to include the whole library. I just want one piece. Maybe I just want Polymer's template stamping ability. Maybe I think that's nice, right? So instead of extending Polymer element, I could just add one mixin to HTML element itself. And that is what my element would be based on. That exposes then this stamp template method that I can pass the template. It will give me back some DOM. And I can choose what to do with that DOM. I could put it in Light DOM. I could put it in Shadow DOM. The DOM also supports declarative event listeners, which is kind of a handy feature of Polymer. And so ultimately, that means that you can use all of Polymer. Or you could just use a feature of Polymer, if you would like, to enhance a vanilla custom element, which I think is pretty cool. So this is still a little experimental, but this is kind of the direction we want to head with these things. So yeah, Polymer element, just a collection of mixins that extend HTML element. Now, another thing you might want to do is extend another custom element. And so I'm really happy to say that in Polymer 2.0, you can once again extend custom elements. We had this back in, I think, Polymer 0.5. We took it out for a while, but it's back in Polymer 2.0. So you can absolutely extend other custom elements. And to do that, your class just extends that element's class instead of your class extending Polymer element directly. So pretty easy, right? And when you do this, you want to make sure that you're calling super in all of those lifecycle callbacks. So super in your constructor, super dot connected callback, things like that, so that that parent element runs all of its setup code as well. OK, so you got your base class setup. It's time to do some configuration. Start by extending Polymer element and then add a static is function there. And that's going to contain your element name. This static is function is really important for Polymer. It's how it actually finds your template later, which I'll talk about in just a sec. The reason we use the static function for this is because ASX classes don't support class properties. You've got to do that via a function, a static function. So we're just dovetailing into the standard there. You want to call a custom element dot define and give it your element name or the tag name. And your class as well. Polymer's not going to be doing this for you. You've got to explicitly register your element. Again, making sure you know that you're using the platform as much as possible. And then you add a config object to it. And this is where you set up your properties and your observers. So this is really similar to Polymer 1.0. Like, just to expand this really quickly, you can see that it looks pretty much the exact same. You have your properties object in there where you define properties, observers, array, just like Polymer 1. And after that, you add your lifecycle callbacks and you're off to the races. So it doesn't look that different from a vanilla custom element, and it also doesn't look that different from Polymer 1. It's kind of like a hybrid of the two, which I really like. We want to make sure that you feel like you are working with the native APIs as much as possible. But we can also tackle some of these pain points now. So let me go through a little demonstration here. I know the code is a little small for the people in back, but don't worry. We're going to kind of scrunch this down and make the font bigger as we add more Polymer. But this is a custom element that I was working on before. My fancy clock thing. And remember, all it does is I'm trying to get a time value in that span right there. So I'm going to take this vanilla custom element and migrate it to Polymer 2 along the way. That's going to help highlight some of Polymer's features. And also, I can demonstrate and sort of tell you how those features work under the hood. OK, so I'm going to start by, instead of extending HTML element, I'm going to extend Polymer element. So far, so good. And then all this code that I've highlighted here, this is all just to keep my time attribute and property in sync. My observed attributes array, my attribute callback, my setter. All that code is just to keep that attribute and property in sync. So I think I can actually get rid of that just by using the config object and a properties block and adding a time property there. So that's eliminated all that code. Polymer is now going to handle keeping my attribute and property in sync. So you might be wondering, well, OK, that's cool. But how did that replace all of that code? Like, what is that actually doing? And so under the hood, when you define a property, what Polymer does is it just secretly creates a setter for you. And it listens for changes in the attribute change callback. The code that Polymer uses is really similar to the code that I already had defined there. When a new value comes into that setter, it dirty checks the value. If the dirty check passes, it saves the value. And then it updates any nodes in the DOM that need to have that value poked into them. That's basically it. So I feel like this actually takes care of our first pain point. Polymer is just going to handle synchronizing our attributes and properties. So we don't have to deal with that, which is nice. Now looking back at the code, the next thing I want to do is I'm going to clean up this inner HTML right here, because it's a little funky having that in my element. I'm not in love with that. So to do that, I'm going to wrap everything in a DOM module. And my DOM module has to have an ID that matches my tag names is property or my elements is property. And this is so if you run your element through a build tool that strips out your JavaScript and your HTML and separates them and moves them far apart and then dumps them in a bundle or something, it's so Polymer can trace its steps back and find your template and associate it with your element. So that's why we have the is property and the ID on the DOM module matching. Next, I'm just going to drop a template inside of here. So I got my template up there. Nice. Now what Polymer is going to do is when it sees that template, it's just going to take the first template it sees in DOM module and pop that into your shadow DOM. So that's really handy. I don't have to write any of that imperative code myself to manually set up the DOM and render my UI or anything. So I feel like that takes care of that pain point about having a lot of boilerplate to set up my element. The last thing I want to do is update the UI whenever my time property is updated. Whenever that value changes, I want the DOM to render. So I'm just going to drop in a data binding. And I want to briefly explain how Polymer's data binding system works under the hood, because I think it's kind of interesting. So in a nutshell, when you create a data binding in Polymer, what is actually happening is Polymer is just sort of finding that element and poking that property into it. So it means if you've got something like this, where you've got to span a little binding inside for text content, Polymer is just going to take a reference to that span and literally set its text content equal to the value that you're updating. And because we're using properties, this works for any value type. So we can declaratively say I've got the sprins element. It's got a friends attribute that takes an array. And I can declaratively say, all right, I'm going to pass it this sprins array. And under the hood, Polymer is just going to say, all right, cool. So I'm going to assign friends this array. Appreciate it forward. Now all this work happens inside of the properties setter that Polymer secretly created for us when it generated or when we put our time property in that properties block. So if we were to peek under the hood and look at what that setter is doing, so this is going to be kind of like pseudo code. But this is essentially what Polymer's doing under the hood. So here's my setter for that friends array. A new value comes in, and the first thing it does is it does a dirty check on that value. It's like, all right, is this different from what I had before? If that dirty check passes, it's going to store the new value. Cool? Then it's going to loop through an array of objects that just contain all of our bindings. So there's literally objects in an array that have references to all the different nodes. And it's just going to loop through that and say, OK, I've got this new property. I'm going to poke it into all these different nodes. And really, that's just how the one-way binding system works. This is also how your observers get called. So inside that setter is just going to call your observer functions and pass at the new value. And if you've done a two-way binding, you've used that notify true flag, it's just going to dispatch a change of it. And elsewhere, someone's listening for that change of it. And that's actually how the two-way binding system works. So it's actually really simple when you see what's going on under the hood. So this is sort of like the hub of the element. The setter is really important. Now, I have a question for you all in the audience, which is, if I mutate my data, so I push a new value into that array, is that going to call the setter? Show of hands if you think it will. Oh, OK, good. You've got smarties in here. Awesome. All right, so no, right, is not going to call the setter. The only way to call that setter is going to be to directly assign something to that property. And so in Polymer 1, we had methods like notify path and this.set, which basically you sort of poke the data binding system. So after you mutated an array or you mutated a sub-property on an object, you had to sort of tell Polymer, like, hey, go update. Please, please. You can still use these methods in Polymer 2 if you'd like. They're still there. And you can use them if you want to very specifically tell the binding system to update one spot as a performance optimization. But we also just made it easier to work with objects and arrays in Polymer. So if you're mutating an array and you'd like to tell Polymer's binding system, like, please, go update, you can either assign the array or assign the object back to itself. This would actually work. So you could do this in Polymer 2. And Polymer is just going to bypass a dirty check for arrays or objects if you do something like this. And we'll just go update all your bindings that rely on that. Or if you're into the whole immutable data thing, you could call this set array can cat. You could pass it a copy of your array or something similar with your object. Or you can just call this new. You could just call this dot set and just pass it the object name. And that'll just tell it to go update all the bindings that rely on that object. So you don't just specifically tell it like the sub thing, the sub property that changed or anything like that. So ultimately, the binding system now is still a bit more streamlined and a bit easier to use. Because I know that was frustrating for a lot of folks. So looking at this final element, I think we've achieved the same level of functionality as the one that we started off with. But there is a lot less code now. It's much easier to reason about. And I feel like we've solved our last pain point there as well. The binding system gives us a nice declarative way to pass complex data, which is great. Now to wrap up, I just want to say, if you're looking at this and you're familiar with Polymer 1, it probably doesn't seem that different, right? And that's really the idea. We really want our primary goal of Polymer 2 is an incremental change that brings developers closer to the platform. So we have an easy on-ramp for our Polymer 1.0 users, while also making it very clear to people that what they're actually using is the native web platform. And so with this release, I feel like we're giving developers a much more productive experience with Polymer. We got less magic and an overall much smaller footprint. So if you want to get some practice with this, we have a code lab area. Our engineer, Keanu, has written a code lab on building your first Polymer 2 element. It goes more in-depth than I've gone in this talk. So definitely go check that out. And with that said, I hope that you all enjoy the rest of your time here at Polymer Summit. And I am super excited to see what you build with Polymer 2. Thanks.