 All right. My name is Kevin. I'm a developer on the Core Polymer Library. And today we're going to talk about apps. So as you probably all know by now, web components are great for building highly reusable user interface components, like the ones on the screen here. And that's not really surprising, because that's kind of a core use case that web components, the specs, were designed to try and solve. But on the Polymer team, we've also shown that web components are great for building applications as well. And in a lot of cases, can be the only component model that you need to build an application. However, that's not to say that web components are all that you need to build really robust, awesome apps using the platform. And we get a lot of questions on the team about what that actually looks like. What's the end-to-end experience look like building applications with Polymer and web components? So that's what I'm going to focus on today. So imagine this scenario. It's a Monday morning. You're sitting in your office, minding your own business. Your boss comes barging in. A boss, kind of a jerky boss, maybe like Matt. He comes running and he's like, hey, I know. I've got a great idea. I know how we're all going to get rich. I need you to build us a real estate listing app. Now, stay with me. It's going to be awesome. It's going to have a really slick, cool user interface, really modern. Users can search for whatever they want. It's going to come up in a nice list. You'll have sorting and filtering in the list. You can switch to a map view with pins flying around showing you where all the houses that meet your criteria are. You can go to a detail view, maybe a mortgage calculator up in the corner. All that data is going to be pulled out of a server and kept in sync as it's changing. The users can log in, bookmark their favorite homes. Of course, we're going to have a responsive layout so that this one app works on all the different form factors we need to target. It's got to load super fast on 3G. It's got to have amazing SEO so users can find all these houses using our site. Of course, it's got to be accessible and international to reach the most number of users we can. And you have two weeks to get it done. So this is the question. Do you feel like you have all of the tools and patterns that you need to get up and start it quickly, to build out features quickly and iteratively to deliver a great, easier experience with maintainable code that's going to scale well into the future? Because that jerky boss is probably going to want you to keep adding features after you get this first proof of concept done. So if we walk through the scenario from start to finish, there's actually a lot of things that we as web developers kind of have to learn and master and know where to start. So we need to make sure that we know how we're going to structure our application to deliver great performance to our users. We want to scaffold out our app from a good starting point so we don't have to reinvent the wheel with every app that we're doing. We want to make sure we're following good patterns for factoring the UI so it's maintainable and reusable. We want to make sure it's internationalized and accessible. We want to make sure that we're following good layout patterns for responsive layout. We want to make sure that we have really solid and repeatable patterns for managing state in our application and making sure the application is easy to reason about. We want good developer workflows for serving and debugging and linting and testing during development. We want to optimize our build for deployment. We want to make sure that we're efficiently serving the application for deployment. It's a ton of stuff that we have to master to get an awesome user experience out. And it can get kind of blurry, trying to figure out where to start. But the good news is there's help. So the Polymer app toolbox we launched at IO last year actually provides answers for a lot of these topics. So the Polymer CLI, the init command there, will scaffold out our application from a good template, a good starting point. We have the app localized behavior, which helps us format strings in our Polymer templates. And browsers actually now have good cross-platform support for formatting numbers and dates through the internationalization API. The paper elements that our elements team produces have always had a really strong focus on accessibility. Our app layout elements provide components for common responsive layout idioms. The serve command in the CLI gives us a nice development server to use while we're developing. Chrome DevTools actually has built-in support for web components, which is really awesome. Shout it out on my custom elements. And we're committed to helping the Chrome team improve the development experience using web components. Polymer Lint provides a static analysis during development. Web Component Tester gives us a framework for continuous integration. And the Polymer build performs a lot of the common optimizations that we need for minification, translation, that sort of thing. But as you can see, there are a few places of the story that I actually sat down and built this application that I talked about for this talk. And there are a few places of the story that I realize that we probably deserve a little more focus than we've given them in the past. So these are what I'm going to talk about today, talking about how we're going to structure the application to hit the best performance, how we're going to factor the UI, how we're going to manage state in an application, a complex application like this, and how we're going to serve it for deployment. So there's a reason that I put performance first on this list. And that's because the number one way you can make sure that your application performance is going to be horrible is to think about it at the very end of the app development, get it all done, and then go, hmm, I wonder how fast this thing loads. So you owe it to your users to make performance the number one concern for how you're structuring your application. And a lot of the front end web development world is enamored with this concept of server-side renderings as a means to good performance, where they'll send down server rendered static HTML first to get something painted to the screen while we're waiting on the rest of the JavaScript to load. But when you think about it, unless your application is just a shell around passive static content, what the user actually wants to do is interact with your application. They want to select a departure date, or sign up for a newsletter, or buy a product, or bookmark a house in our real estate application. And server-side rendering really helps with none of this. It just gives them something to look at until the code loads so they can actually do what it is they came out to do. So if you still have to send a huge bundle of JavaScript down to your users to transform that initial rendering into an interactive application, your users are still going to hate you. And if you don't believe me, what I'm going to show up here are two actual real-life server-side rendered applications. So I'll get this going. So as you can see, they actually render to the screen really fast. And they give you this impression that you can start using the application. It's there. I've got this throttle down to 3G. So this is running in Chrome DevTools on mobile-type settings. And you can see it results in this horrible experience for the user. They have to sit there wondering when the thing is actually going to become interactive. And this is not to say that server-side rendering is wrong or a bad technique to have in your arsenal for good performance. In fact, Trey Sugard is here to give a talk tomorrow about some really awesome work he's been doing on being able to server-side web components on the server. But rather, it just says that there's just really no shortcuts to delivering a good user experience. We just have to be focusing on the right metrics. And for a lot of applications, the right metric is probably not the time to first paint, but the time to interactive, the time until the user can actually do something on your site. And the best way to ensure a good time to interactive is this. Don't make the user wait for anything they didn't ask for. So that means only send down what the route requires in as few round trips as possible, sending as little duplicate information as possible between routes. And that sounds easy enough. But historically, it's been fairly difficult to achieve. And this is why on the Polymer team, we've been working really hard to promote and get people thinking about the purple pattern. And this gives us a straightforward pattern for factoring applications for optimal delivery. So in short, we'd start by factoring our application around decoupled routes that can all fit back together into an interactive experience. And then we're going to push down only the code that's needed for the initial route as few round trips as possible. So only what the user asked for in their first URL, that's the only thing we should be burdening them with first. And then from there, we're going to render and get that initial route interactive as quickly as possible. And then while the user is enjoying the route that they asked for, the service worker can boot up. And in the background, we can be pre-caching the rest of the application. So the code needed for all the other routes in the background so that when the user is ready to move on to other parts of the application, we can then lazily import the code that's needed for the remaining routes right out of the cache and get those rendered quickly as well. So we summarize this as purple. Push, render, pre-cache, and lazy load, lazy import. And it gives us a nice pattern to ensure that we're giving the user exactly what they want and no more. But that's not good enough just to follow the pattern. We actually have to be measuring. We have to measure the metric that makes sense for our app. And we recommend using WebPageTest for this. So they've recently added an easy mode, so you can just go to webpagesst.org slash easy. And it'll open up the site pre-configured for testing on mobile devices. So you just want to check the Lighthouse checkbox there. Drop in your URL, hit Start Test. And then it will run a performance test of your application using real mobile devices and real throttle networks. Once it's done testing, you'll get a result page, something like this. If you click into the Lighthouse score, you can scroll down just a little bit. And in there will be the time to interact. So this is a really good metric to be focusing on when you're building your app to judge how good your experience is going to be. And then to ensure a good experience, we recommend setting a budget for yourself. And we like to target around 3 and 1 half seconds on these mobile 3G networks. And on these settings, the first byte from the server actually doesn't get down to the client until two seconds. That's because SSL negotiation requires a lot of round trips to the server. And so that eats up a huge amount of your budget, right? So that only leaves you a second and a half to get something interactive, the thing that the user wanted to do on your app, get that interactive on the screen. And we found that this 1 and 1 half seconds of budget, if that's what we're budgeting, translates into about 50 kilobytes of code. That doesn't sound like a ton. But with new Polymer 2.0, that starts at around 12k. So that leaves you about 40k left for your budget. As you heard in our last talk, we're doing a lot of work coming up in the future to make sure our element sets are highly optimized so that they can help you fit into this budget. And we found that the best way, anytime we're putting our recommendation out, what we want people to follow is to give it a name, right? Because names are powerful. As soon as you have a name, you can talk about it with other developers and that sort of thing. So we're calling this one purple 50. So this means apply the purple pattern and budget yourself to 50 kilobytes. That's a good rule of thumb to ensure that you're hitting a good performance. OK, so let's see what applying the purple 50 pattern looks like in our real estate app here. So we're going to start with an application shell that's responsible for handling the route on the client, loading the top level components for the route. And then we'll think about breaking the application down into meaningful routes. So for this application, we might have a home route and an explore route and a detail route. So we'll start with those features and then we can add more later on as the boss comes in and asks us to. And then for each of those routes, we're going to build a custom element that encapsulates the view needed for each of those routes, right? So here we'd have a homepage, explore page, something like that. And then following the purple 50 pattern, we're just going to try and keep an eye out on the code that we're putting into each route and try and stay within our 50 kilobyte budget. So this is the general idea how we're going to approach meeting all of our performance requirements and ensuring we have a good structure for the app. OK, so we've got the structure down. Now let's move into how we're going to start building out our user interface. So this usually involves taking UI mocks that designer might have sketched up and then factoring those drawing boxes around them, bringing them down into individual components. Some of those we can get off the shelf, and others are going to be our application-specific components. And then we'll use composition to build those all back up into our final application. So we're going to want to leverage reusable components wherever possible, right? Because the best line of code is the one that you didn't have to write, right? And just like MPM is kind of our go-to source for JavaScript libraries, webcomonents.org is our go-to source for reusable web components. So we can go there and see what in the catalog might fit our needs in any given application we're trying to build. So for a lot of our app UI, we can just stand on the shoulders of others in the community and not reinvent the wheel where we don't have to. So if we look at our mocks, we can get elements out of the catalog, maybe tabs for the navigation here, maybe some icon buttons, even the Google map, right? There are components for things like maps in the catalog as well. But again, using custom elements are not just for reusable components. We can use those to build our application-specific components too. And this has a lot of benefits over using a non-standard component model, some other library to do your application. So among these, so we can achieve a smaller payload because we're using the component model that's built into the browser. We don't have to download code to get that. Whenever we're scaling an app to a large team, encapsulation is really important to help with that coordination problem when developers aren't all working really closely together. And we get encapsulation for free with web components built into the browser. Like I mentioned before, Chrome has really awesome DevTools support for custom elements in Shadow DOM. And most importantly, our components aren't locked into any given framework silo. I want to pause here because that's a really important point. I don't just mean that you're just locked into a different silo. That's not the point. The point is that as long as you're using custom elements as your component model and properties and events as your interface for the component and Shadow DOM to encapsulate the rendering, really how you transform the inputs to the component into whatever the component does is purely an implementation detail of the component. We have a really nice abstraction between the interface and the actual implementation. So we can actually extend from whatever base class we want without losing interoperability with other elements in our application. So if we were building an application, we could build the whole thing by extending Polymer element, our base class that we showed with Polymer 2.0. But that's just one choice. Down the line, we could switch some of our components over to using the simple element base class that Steve just talked about building. And those can totally work side by side in your application with Polymer elements. We could try Skate.js. Trey is here. And he might sell you on Skate.js. You could try that out in your application without switching the whole application over. And someone is bound to make some new, better web component base class in the future that we all might want to shift over to. And we can do that incrementally over time without throwing our application away each time. So think about that. If you wanted to change from popular framework 1 to popular framework 2 today, that's a total rewrite. You throw out your application. When we start building our applications out of web components, it gives us this ability to incrementally change over time without having to throw everything away and without losing the ability to innovate. So back to our real estate app. So let's take a look at how we'd factor our application views down into components. So let's just focus on this one route, this explore page element. And then we can use reusable elements from the catalog. So the Google map, the paper icon button, we can even use native selects here, style them a little especially. And then we might want to factor some of the rest of the view down into other application-specific components that we're just going to compose together. So we're just going to keep kind of breaking down and composing back up until we've got the final view for our route. And then at the top level of our application will be our app shell. And this component is responsible for the top level layout of the application. So the real estate app is our app shell. Inside of there, we might have app toolbar, paper tab. So it's doing the layout and the navigational components. And then the app shell is also going to have the code for the router. And then the knowledge of how to lazily import the components needed for each route. So if I go to the explore route, the app shell would be responsible for loading that explore page element and getting it rendered and interactive. If the user changes to a detail route later, it would load and get that element rendered. So to get started with an app shell template set up for this sort of factoring, you can check out the Polymer starter kit template in the CLI to get going. OK, so we talked about structure for performance factoring the UI. Next, we need to bring our application to life by loading it with data and managing state changes in the application. So application state management is one of these areas that the web platform has really had the least to say about. And so it's an area that we get a lot of questions about. It's probably our biggest area of confusion and questions and that sort of thing, and requests for guidance. So two years ago at our first Polymer summit in Amsterdam, I gave a talk called Thinking in Polymer. And it put forth the concept of a mediator pattern for how we think about composing and coordinating state changes between components. So just a really quick recap. In short, a mediator owns a scope of other components. So it owns them and is responsible for propagating data down to the components, listening for events from the components to handle user interactions, that sort of thing. And then based on those events, perhaps mutating some data and propagating those changes back down to the components it owns, as well as up and out via events. So the mediator pattern is really useful for creating reusable standalone components that can handle their own complex state changes internally while still communicating the changes up and out. And that's because it encapsulates the statements management so it's portable. So these are the kind of things you're going to find in webcommodents.org, things that you get off the shelf. They don't have to tell you how to do your state management. It kind of comes along with it. And using this pattern, we've shown that you can actually just kind of keep composing mediators into mediators. And as you keep building that up, you end up with a final top level mediator that's mediating other components, and you can build your application out of that. So it's kind of the turtles all the way down mediator concept. However, the community has also shown that there can be benefits to having less granular and even global mediators of state. So it's kind of a trade-off space in a spectrum here. And particularly as components become more and more app specific and are largely used to compose more generic components together with application-specific logic, having one mediator for all application data can make the application more easy to reason about. And it opens up nice developer workflows that we'll see in a minute. So these global mediator patterns, so Flux is one really popular example, popular in the React community, they kind of formalize this concept of having one central place to put all the application state that flows down to components, and one place to dispatch events that cause application data to be mutated and passed down. And so we can just think about these kind of global mediator patterns as the mediator patterns. The instance of the mediator pattern is just at a global level. Now, there are lots of choices out there to implement the global mediator pattern, kind of too many to go to in this talk. But a lot of times developers just come to us and say, just tell me one to use. Just tell me anything that you know is good, and I'll do it. And if you're looking for that kind of answer, we actually think Redux is a really good choice. It makes really well to web components, and we know that people have had success for it. So Redux is really simple. It really has very little magic in it. It implements a really simple mediator pattern. And there's a really strong ecosystem that Redux has built. The library actually starts really simple, very easy to understand concepts. And as the needs of your application become more complex, there tend to be ecosystem-based answers to handle that complexity. So a lot of times, these take the form of add-ons that help you manage async flows of data in and out of the server, for example, or complex flows through the application that the user is going to take, that sort of thing. So let's just take a look at what applying Redux to this application would look like. So first, let's introduce some terms. So in Redux, the global mediator, they call that the store. And so for passing data down into the application from the store, there's a subscribe callback that elements can call to be notified of any changes to the global state in the store. And then actions can be dispatched in place of events. Actions are dispatched to the store to tell the store to change the current state of the application. And those are done using what they call reducers. So these are functions that we write and give to the store that tell how to change the state based on actions that happen. So like I mentioned, there's a bit of a trade-off going from localized state management, where it's all self-contained, to global state management, where you put it all in one spot. But one of the key benefits is that it opens up really nice developer workflows, like the DevTools that ship in Redux. So this is a screenshot of the DevTools that you can install into Chrome. And they just sit there in your DevTools. And on the next screen, I'll show what this looks like. But basically, because we're centralizing where all the actions that can possibly mutate the state go, it's able to log everything that's happening in the app that led to a state change. And then because all the state is sitting in one spot as well, it lets us see all of the state altogether. So that helps make it a lot easier to reason about as you're building an application. So here's an example of using the application in the DevTools. And as you can see, for every user interaction that happens in the application, in the action log there, we get an action that's logged. So we can have a log of every event that's leading to a state change and actually see the state changing over time in the application. So for each user action, you get action state changes. And then what's really neat is it introduces this concept of time travel debugging, which you might have heard about. So it lets you scroll back up into the action log. And because the DevTools are snapshotting that global state object at every action, you can actually play back. You can go back in time, kind of look for, for example, if you had a bug, like maybe this little popup got screwed up there. I can actually jump back in time, find the action that caused the state to change in a way that caused the bug, and makes it a lot easier to kind of debug your app and find what's going on. OK, so there are lots of ways to connect custom elements to Redux. And it's fairly simple to do so. So I'm just going to show one way there's lots to do it. But one way is to build your elements as generic views that just accept properties and fire changes out and don't mutate any state themselves. And then what you can do is then subclass that element so that the generic element you could use in any application in your lineup, that sort of thing. But then you can subclass it and connect it to the store of a given application. And then in the subclass, to connect it to the store, we would just have the element called the subscribe callback to Redux to get any state changes and set those into properties. And then we can add event listeners, just normal DOM event listeners that listen for events and dispatch actions to the store that are going to change the data. And one other kind of pro tip I want to point out is that if you're kind of moving and looking into global state management techniques, most of them don't come out of the box with a way to kind of separate all of the state management code. They kind of lead you towards having a big blob of all of your application, its global state management. So you put it all in one spot. And this kind of runs afoul of our purple concept, right? We only want to load the code that the user actually needs for the route that they added. So that's something we want to pay attention to that we'll see here. So just very briefly, so pretend that Explorer page is the element that we created, the view just takes properties in and events out. And we're going to subclass it. In the constructor, we're going to call Redux to the subscribe method. We get a new state object. And then we simply dereference any state that's needed in this particular component out of the store and set those into properties. And here I'm using Polymer 2.0 Set Properties API, which allows us to set a batch of properties to an element once really efficiently. And then on the other side, we want to dispatch actions and event listeners. So for any events that happen that should cause state to change, we just add an event listener and then call Redux's dispatch method to send an action to the store. And here I'm using what Redux calls action creators, which are just functions that we write that take a parameter and return an action object. So I'm creating an action and dispatching it to the store based on the event. So we're going to do that for any events that our application fires that needs to mutate state. And then last, we want to make sure that we're lazily loading any of the state management code along with our element and not putting it kind of centrally in the application. And the way I've done this here is Redux has a lot of extensibility hooks. I wrote a very simple enhancement to Redux that allows me to add an API to the store to lazily install the reducers, the things that kind of manage state changes into the store as more and more elements come in. So they're lazily adding the state management code to the application. So here the listings reducer is responsible for handling any changes to the listings. I load that along with this component, which again, via the purple pattern, is being lazily loaded just for that route and installed into the store. And then likewise, any action creators, any kind of action-based logic, you want to make sure that you're importing that along with the component as well. So we will continue experimenting with patterns for state management and how they can fit into web component-based apps. And I wanted to also call out a community library called Polymer Redux, which takes a declarative approach to binding Polymer elements to Redux. So that's something you could also check out. And like I said before, there's a ton of innovation happening in the community. And Redux is just one of those. Most of those can also be happily paired with web components. So I encourage you to share ideas, how you're building applications, share them with us, share them with other people at the conference today. All right, so we're done managing state. Finally, we have to actually serve our application to our users. So we'll need to host and serve it to our clients. And although a lot can be accomplished by statically serving our client application, we feel that there are a few key minimal features that are required to be implemented on your server to actually get the best user experience. So these include serving the app shell for all routes. So based on any route in your application, making sure that you're serving the app shell, which is then responsible for lazily loading the components you need. Using HTTP to push when possible to reduce round trips and to serve granular components when that makes sense to improve the efficiency of your caching. And when HTTP to is not possible, then alternatively serving bundled assets but that are bundled per route. We wanna make sure that we're sending the optimal code down for the capabilities of the browser. So for browsers that implement ES6, for example, we might wanna take advantage of native custom element subclassing by sending non-transpiled code, for example. And then finally, we wanna make sure that we're serving SEO compatible output for any bots that might visit our site. So we've been doing a lot of work on a reference server that does all of these good things that we're calling purple server node. And that's designed to work hand-in-hand with the outputs that come out of the Polymer build system. So it's a node-based server that's set up for client-side routing. And then it has a lot of extra features to do these kind of smart things. When I was doing a run-through a couple of days ago, Chris, awesome developer on our team, was like, you're kind of short-selling purple server node by using that kind of lame database clipart there. Can't you jazz it up a little bit? Because the server is actually pretty awesome. So I put some sparkles on there. I don't know if that made Chris happy. But basically it has some presets in there that allow us to, that can automatically detect the capabilities of the browser and serve the optimal code for each. So for browsers that have ES6, for example, it can serve raw ES6 code so that we can take advantage of the native ES6 subclassing of custom elements in the browser. It can also, and then for browsers that don't have ES6, we can serve the transpiled code as well. It can also differentiate between browsers that have push so we can serve granular components to reduce round trips when possible and serve bundles for non-push compatible browsers. And then it will kind of do the permutation of things and serve the right set for the capabilities of the browser. And then last, kind of under this heading or I'm calling bot, so these are things like Google being search crawlers, that sort of thing, as well as social snippet generators that kind of create the cards that show up in social networks. We're actually integrating purple server node with another project that we're working on on the Polymer team aimed at tackling this SEO problem with web components. And that will actually serve rendered HTML, fully rendered HTML that's compatible with SEO and social snippet generators. And I'm just going to tease that today because we have a whole talk on that tomorrow that you guys should stick around for and check out. So you can check out the beta of purple server node here. Give us feedback. So this is kind of set up for you to deploy onto a hosting site like App Engine, something like that. Sit behind a CDN and get really good serving efficiency. OK, so with purple node server, we kind of fill in the last big gap in our story about how we're actually going to deliver these awesome experiences using the platform. And hopefully, you feel more confident now that you have all the tools you need to build robust real world apps like this real estate app. And at the beginning, I said we had like two weeks, right? That was our setup. We had two weeks to build this. So to be honest, I didn't have a whole lot of time to kind of put this talk together, but I really wanted to build an app. And actually, I was able to build this out in two days. This much. It's a proof of concept. I still need to do a little more work to get the demo ready. But of that two days, like a full half of it, like a whole day was just generating a bunch of fake real estate JSON so that I didn't get sued by people by showing their house in my talk. So hopefully, from this proof of concept, I feel that I'm way more confident now that I've got a really well factored UI with components that I can reuse across other applications. I've got easy to debug state management that will scale well to adding more routes, adding more features. I know I'm going to be set up well for performance. I've got a structure that scales well for performance with the purple 50 pattern. And I've got a great serving environment with purple server node. So hopefully, you feel like you can be this productive with the web platform too. So we're going to continue working to take all of these kind of best practices that we come across as we kind of tackle more and more challenges on the web platform and provide guidance and provide features and provide products to help move this along. Thank you very much.