 Thanks. So I work for a company called Jack Henry and Associates, which probably none of you have ever heard of. But we write U.S. banking software. So why am I talking to you today? Well, in that role, I get to contribute to a lot of open source projects, Polymer being one, another being Google's Closure Compiler. But today I want to talk to you about a new project, and that's using Polymer with Webpack. Now, I can tell from the amount of questions I've already had that there's a lot of interest in this subject. So hopefully I can give you all the detail you need to actually use this today. Before we dive deep into the internals of how Polymer and Webpack can operate together, I want to talk a little bit about why this is important and how we got here. So my team has been building JavaScript applications for a long time, number of years. But lately we've become pretty disenfranchised with modern monolithic JavaScript frameworks. What we found is over time, even though we tried to guard against it, almost every file in our app became tightly bound to the framework. So if we started up a new project, we didn't have a good set of choices. We were either making the same framework choice we had already made, which kills innovation, or we were rewriting and duplicating code we had already written, which is never fun. The other thing we found with this is modern JavaScript frameworks tended to have a much shorter lifespan than the products we were developing. So once they became deprecated, we were either forced to upgrade or basically maintain old code, and no one likes that. So the idea with Polymer and the Web Component Standards is these are baked into the platform. And as we all know, there's a rule out there. You can't break old code in the platform. So if we're using platform-based code, we're guaranteed backwards compatibility. Great. This is perfect. This gives us our long lifespan. In addition, Polymer as a library was just really light syntactic sugar over the standards. And in fact, they went out of their way to get to not reimplement or even make easier in some case native APIs, which we loved. Well, it might require us to write more code locally. That code was then closer to the platform, thus producing our longer lifespan. So with the promise of Polymer 1, I dove into it fully with my team and helped develop this rich component library that we could share among all our projects of UI elements. The idea being that as each project spun up, we could reuse the elements we had already built just like Rob so aptly demonstrated and talked about, but not be locked into this huge framework. So we did it. And in most cases, things worked great at the element layer. When we put a Polymer element into an old Angular project, it worked. Now, there's caveats. Angular couldn't see into ShadowDom, but that was intentional. We expected that. But once we got beyond, hey, this actually works. How do we build it? Life was not near as fun. The really interesting thing came down to Polymer being mixed content of HTML, CSS, and JavaScript. Now, like most teams, we'd been through the full gamut of front-end build systems. We started with grunt, we moved on to Gulp, and we even experimented with just using NPM scripts and rewriting Gulp ourselves. And kind of actually truth be told, today have projects that use each of these. It didn't matter which of those build systems we choose, integrating Polymer was not fun. One of the problems we encountered is when you did this, Polymer used HTML imports. Everything else out there uses modules of some sort. Common JS, ES modules, AMD modules, it didn't matter. They used a module-based syntax. So those dependency trees, there was just no good way to mesh them. What we ended up having to doing felt pretty icky, actually. What we have to do is create a synthetic Polymer import element and add any component we might want to use anywhere in our app to that import. And then use it, then we can use it over and reference it over in the JavaScript. But when we switch back or refactor, we have to remember, oh, now I no longer use this, I need to remove it from my HTML import over here. And be careful, because I need to make sure I really am not using it anymore. What happens is on larger projects, we ended up writing custom tooling to try to make sure and add checks that those two didn't get out of sync. Again, not a lot of fun. What we found ourselves struggling with was just the sheer weight of the build system code. Over and over in my team's retrospectives, it keeps coming up. It's got to be a better way. I don't like writing all this build system code. The other clue that there was a problem that needed fixing was the build system itself started requiring substantial documentation. Not the code I set out to write was a build system. I set out to write a product for my company. Enter Webpack. So let me first be clear. Webpack is a build system. And I'm talking about solving build system problems with a new build system. It's okay. It's totally worth it. I know you've heard that 100 times. Give me a chance to prove that this is the case. So Webpack is a little bit opinionated, but tends to be opinionated in the ways that help you as a developer instead of getting in your way. For instance, there's a lot of tedious tasks that we work on in build systems that Webpack just bakes in. Calculating the hash of a built file system so that you can add it to the name to do cache busting. There's 14 bajillion plugins that do that in-grant and gulp and name your build system here. Webpack has it included. Don't even mess with it. Just use the naming convention and away you go. One of the other big benefits of Webpack is it comes with the Webpack dev server, which is a local development server and an extremely stable file watcher. And I reference that because if you've tried to roll your own dev server, you know how easy it is for an exception in your build process to crash your dev server. That doesn't happen with Webpack. One of the other defining points about Webpack is the dependency graph. This is nothing new. Lots of build systems have a dependency graph where they crawl your site and find all the used code. The difference with Webpack is it's all your code. Not just your JavaScript, your CSS, your fonts, your images, all your static assets also get added to the build graph and copied to the distribution folder. That means when you stop using them in your code, they don't get copied to the distribution folder. This is magic and just works and is something I never want to deal with out again. There's one caveat with Webpack, though. It only handles JavaScript modules. So how can we add static resources to our dependency graph when they're not a JavaScript module? That's the job of a Webpack loader. A Webpack loader takes one input file and its sole goal is to transform it into a format that the rest of Webpack can handle, a JavaScript module in some way. So this makes most sense when we start out with ECMAScript modules. So maybe we're writing latest and greatest stage two proposal ECMAScript and we just want to transpile it down to ES5 for delivery. Hey, the Babel loader does that, JavaScript to JavaScript, no problem. The next part comes with TypeScript. That's a little bit different. In a lot of ways I'm in a different language. Well, the TypeScript loader simply does what the command line TypeScript compiler does and converts it down to a JavaScript module. Still okay. Now we start getting interesting. What about SCSS files? So there I might need two loaders and you can chain loaders in a Webpack. So we're going to pipe by file through a SAS loader, which is going to create a CSS file and then we're going to pipe it through the CSS loader, which will make a style module which is JavaScript and can be dynamically add styles at runtime. Pretty cool. So Webpack just handles that. After we've got our loader set up, the next thing we deal with in Webpack is plugins. And plugins can deal with any part of the rest of the compilation life cycle. So the easy thing, the natural thing everyone thinks about is something like minification, Aglify.js, or whatever other minifier you want to use. I tend to prefer Closure Compiler. It's not for everyone. But in that case, that's only a small piece of the puzzle. Webpack has plugins to do framework specific things. Webpack has plugins to handle licensing. Webpack has plugins to do internationalization. Optimize modules so that modules don't get duplicated or get bundled in correct ways. On and on. Keep in mind, a plugin works a little bit different than a loader because it's working across multiple files where a loader is concerned with a single file. One of the other strong benefits of Webpack is how easy it makes code splitting and lazy loading. Again, these are not new concepts, but they've been strictly painful in most build systems. You as a developer have to maintain one set of files with how does my input map to my output files, and in your code, you have to keep in sync as well and make sure you import them in a way that that actually works. Webpack does away with all of that. Instead, it looks at how you wrote your JavaScript and builds the modules for you. It also adds the loader for runtime work, so you don't have to do that either. You don't need a separate module loader. So, Webpack adds it as part of your build. Let's take an example. So, in this case, we have a main JavaScript bundle where the whole app is a single bundle. But let's say that last section, aptly called huge, is rarely used. We want to split that off and lazy load it and make our initial payload smaller. All we have to do is change how we import the module. So, instead of using a standard import statement, which is static, we changed to a synchronous import statement. And don't worry, we'll talk about a couple different formats for this. This is the new dynamic import statement for ECMAScript. It's promise-based. So, we're importing the same module just in a different way. Webpack recognizes this, automatically pipes out huge.js code to its own file, and adds the necessary runtime code to wire it up for me. By the way, I keep saying injects run type code. That's typically pretty scary to anyone who really likes to know what's going on in their JavaScript. The runtime code for this, uncompressed, is about 150 lines. So, don't feel like a lot is going on here. It pretty much stays out of your way and does the bare minimum and does it well. So, with Polymer, we're obviously going to need a loader. Again, the tricky part here is that a Polymer element is mixed content. It's the problem with build tooling in the first place. So, the Polymer Webpack loader recognizes the types of content in your file and processes each one a little bit differently. So, the first thing it does is it goes through and looks for any HTML imports. Instead of relying on HTML imports, it simply changes this to a JavaScript import statement. Great. That one's easy. The next one's a bit trickier. What to do with the DOM module and the template. In this case, we just make a big string out of it and call a custom runtime function, which registers it with Polymer's DOM module loaders at runtime. So, it just adds it in. And then the last part is the script tags. So, external script references also become module import statements. And inline script tags just become the module body. So, splitting up, handling all three different contents, what we end up with is an all JavaScript bundle. One of the side effects of doing this, wait for it, you're no longer using HTML imports at all. So, now you're not relying on a spec that's not going to be implemented outside Chrome and you've got a JavaScript bundle, which then the rest of your tooling is free to optimize in the way it sees fit. So, one sticky point with all Polymer developers has been, I just want to import from Node modules and use it in my element. With Webpack, you can. You don't have to do anything. It just works. You're already in a JavaScript module. One little note here. We're going to start and I'm going to talk about this multiple times. The script element has type equals module. This is a clue to everyone who looks at your code that you're opting into module syntax and that's a little bit different than normal. You may have code that's not all using NPM yet if you're using Polymer, so you can also configure Webpack to do the same type of lookup from your Bower components. All right, so we talked about adding static files to the graph. What about images? Well, typically with HTML files, in Webpack you would use the HTML loader. It would scan your file, look for any image sources and add them to the dependency graph. Now, adding an image to a JavaScript module dependency graph may seem a little bit odd, but in here Webpack again really shines. So all it does is you typically use a file loader for images and that loader's job is simply copy this file using the naming conventions I specify to the distribution folder and the JavaScript module part of it is the path name I just copied to. So then I have a valid JavaScript module, which in this case just returns the image path and everything just works. The trick is Polymer elements we've already done all this manipulation on, so we can't use the normal Webpack bundlers and loaders to handle this. The Polymer Webpack loader does this for you. It's internally going to pass your HTML content off to the HTML loader and let it do the same thing and it's going to do a similar set of steps with your styles. Both of these can also minify as they go, giving you more bang for the buck. So there's a few differences in how you write your code when you're using Webpack. One of the things to note is that in Polymer, to lazy load an element, we typically use Polymer import href. So that uses HTML imports. That's not going to work. Instead, we need to use JavaScript asynchronous imports. And like I referenced, there's a couple different varieties. The ECMAScriptDynamicImport statement, you can hear more about this tomorrow in Sam's Talk, is the easiest way in the recommended way to do this. It's promise-based, so you put your path to your component and then say .then and use the results. But perhaps you're not there yet and you'd like to use CommonJS. So this has actually been supported for a long time, no one just knows about it, but there's a CommonJSRequire call called require.insure, which takes a callback and does a very similar thing. It's job is to asynchronously load a module and then call the callback when it's ready. So we can use that in Webpack today and then we've got our dynamic import. Both of these import statements work in Webpack and will be treated as a split point for code splitting. Now, you'll notice in my paths that I'm importing HTML files. Don't let that trip you up. At this point, those files have been packaged as a JavaScript bundle. So it's totally appropriate to import them using a JavaScript function. The Webpack config itself is kind of interesting to look at. I think of it as kind of the best of both worlds between the grunt configuration file and gulp program mobility. You don't have to do near as much work and it doesn't get near as out of control as grunt does, but it's a lot more declarative than gulp ever was. So like most systems, Webpack is going to start from an entry point or a set of entry points. With Polymer, your entry point is probably going to be an HTML element and that's just fine. The loader will do its job and everything will just work. But like I said earlier, we probably also want to tell Webpack where to resolve and look up named modules from. By default, it's already going to look in node modules, but we might want Bower components too, so we just override the module lookup algorithm and specify two folders. It will now look in both and I don't even have to worry about it. Now we need to configure our loaders. Loaders are just a set of rules. Each rule has a test that helps filter down what files it needs to look at. Normally the test is just a regular expression on the file extension. Followed by that as a use block with the list of loaders I want to run through. One note on this, it runs last to first. So in this case, we're running the Polymer Webpack loader to create a JavaScript bundle and then running Babel to transpile that bundle to ES5. And last, you can use include and exclude definitions to further restrict where it looks. In this case, I'm restricting it to my source components folder so that the rest of the HTML in my project doesn't get treated as a Polymer component. Now, remember, everything in Webpack is a JavaScript module. Modules do not have the same semantics as scripts. Probably the biggest difference here is as soon as you use a module, you're no longer in the global scope. The easiest way to address this with Webpack for your own code is simply to declare your elements on the window element, thus forcing them to be global. Now everything works again. You only need to do this if you need to reference the class constructor or the class itself somewhere else. If you don't need to reference it, if you just need to define it, you don't have to do this. But if you need to reference it somewhere else, you can declare it as a property on the window element. But perhaps you'd like to use a more modern method. You can also use module importing and exporting to do this. Again, notice the script type equals module. The import and export keywords are not valid in a browser unless you're already in a module. So they weren't working in a script tag. So by adding type equals module, I'm telling the browser that I'm in a module. Now, one note, Webpack doesn't care one way or the other, you're going to be in a module. This is just an indication to anyone else looking at your element what's going on. So now that I have script typing module, I can just say export, default, class, whatever. And that's now exported. Other things can now import it. One little note here. You can't actually import from an inline script tag. So while this is valid syntax, it doesn't really make any sense unless you're using Webpack. And then that block of code will become my module body and I most certainly can't import from it. So if you're trying to live in two spaces at once, this might be a good way to handle it. But a lot of the code we deal with isn't our own. It's library code. And for that case, we can't go change how it was declared. Webpack has a whole set of shimming options where you can at build time make minor adjustments to how code is declared to make it work. So in the top I've got a script tag and I do mean script at this point, not module, it's in the global scope and it's called add some mix in. I need to use it in another module. Well, since it's no longer going to be in the global scope, Webpack's exports loader helps. In that I can declare exactly what file I'm talking about and I say I need to export the add some mix in symbol. Webpack will automatically add the export statement to the bottom of my file which doesn't interfere with source maps and everything goes from there. On the reverse side is the provide plugin. So let's say a different piece of library code expected that add some mix in function to be global. Now it's not. The provide plugin says if any part of my compilation tries to reference add some mix in globally, add an import statement for it so that it's defined locally. So you can shim back and forth in that way. Now, if you have a large existing code base that uses a lot of script semantics, you're going to be doing a lot of shimming. So just keep that in mind. Don't expect this to be just a plugin and it works for all scenarios. There is a little bit of play around here. You can do it, but there will be a lot of configuration to make that work. One of the other really cool things about Webpack is it natively normalizes modules. And by that I mean it understands an ECMAScript static import, an ESNex dynamic import statement, the common JS require call, and the asynchronous common JS require.insure call. If all the rest of your code is using language semantics that are already supported in your development browser, you don't need a transpiler for modules. Why is this a big deal? Well, one, it speeds up your builds not to have to run them through a transpiler like Babel. But two, debugging is a whole lot nicer when you've got the native untranspiled code right there to look at. One of the gotchas here, though, is that as you start using Webpack and module syntax, especially with Polymer 2 and earlier, you're going to lock yourselves in very easily to Webpack-specific syntax. That's okay for your own elements. Just be aware you've limited the ability to share your components with others. Here's an example. We're importing from node modules. Awesome. This works. We're using the node module resolution format. Except that anybody else who uses this element also has to be able to use the node module resolution format. So we've just limited our ability to share this to webcomponents.org. That's just not allowed. So just keep that in mind. Another thing to keep in mind is that how a browser resolves a URL and how it resolves modules and how nodes resolves modules, all three of these things have different semantics. For instance, the top link in the HTML import section is mycomponent.html. Well, you look at that and you know that that means find my component HTML in the same directory I'm currently in. Except that if you're translating that to a JavaScript import, that could mean import from node modules or a sibling folder. So to get around that ambiguity, we require that the import statement has a dot slash. So the Polymer webpack loader is going to add that for you. But what happens if you wanted to use a named import for a component? Well, webpack has specific syntax for this and it comes up in any place a URL is used like CSS background images. By adding a tilde character in front of the URL, you tell webpack I really want this to be a module resolution and not a URL lookup. But again, that's very webpack specific, so be careful where you use it. One of the really tricky things that happens when you get away from HTML imports is that the polyfills start feeling very fragile to get bootstrapped. You have to do this precisely in the right order. So a couple things, one, if you're transpiling, you'll need the custom elements ES5 adapter and any browser that has native custom elements support. But you can't transpile that folder and you shouldn't bundle it with any other polyfills because by design it can throw an exception. So watch out for that. The next thing is the rest of the web components, polyfills, if you're using the web components loader load asynchronously. So you have to delay your main bundle load until after the web components ready event fires. Now, if this all seems a bit tricky, it is. But there's a demo folder in the Polymer webpack loader that shows exactly how to do this and I recommend you just reference and follow that and try not to overthink this. A lot of Polymer developers always seem to ask, how do I use a CSS preprocessor like SAS with my Polymer elements? The standard answer is you really don't need them, which is true, but not what they ask. And sometimes when you're working with other frameworks, you just really want to reference those global color variables without using it. The problem is that the shady CSS polyfill features can't see an external style sheet. Adding an external style sheet reference like I'm showing here is completely supported by the ShadowDOM spec. The imported styles will automatically be added to ShadowDOM and properly scoped. But again, the shady CSS polyfill doesn't see it. So older browsers, you can't use custom CSS properties. And in no browser can you use the add apply mixing syntax. The Polymer Webpack loader has an opt-in option that in cases like this, it will inline your CSS into the element. So you can run your preprocessor on it and then the inline elements will let this shady CSS polyfill match it and you can have both worlds at that point. All right. What about Polymer 3? So all of the functionality that the Polymer team is moving towards with Polymer 3 can already be used with this loader. In fact, it's doing almost exactly the same thing. You can bundle and use ECMAScript modules as you need right now. Where are we going with Polymer 3? Well, so maybe you're not thrilled with the idea of authoring your HTML inside a template literal in ECMAScript modules. Don't worry. Webpack should be able to do that for you. So we'll just run the same process we run today and stick it in the template property once Polymer 3 is far enough along in the development that that makes sense. My team, in fact, I didn't actually do most of the code. The developer who did is with me. We wrote this to reduce a lot of the build friction we were seeing. We're using this in production today with AngularJS applications. I also know of developers who are here who are using it in TypeScript projects. My team is going to continue to collaborate with both the Polymer team and the Webpack core team to improve the experience in Webpack and Polymer for both of these. To give you as a developer the best of both worlds, we really try to design this to leverage the strength of both systems rather than try to let them fight together. A couple takeaways for you in the Polymer Webpack Loader project, you're going to find that demo project I referenced earlier. Rob Dotson actually wrote it. It's a great reference point for just the bare bones examples of what to use. But in addition, my team maintains a copy of the Polymer starter kit which shows the changes needed to make to a Polymer app to build with Webpack. That link is also referenced. You're free to reference both. Thanks, and I'll be around later for Q&A.