 Welcome, everybody. My name is Gray Norton. I'm an engineering manager on the Polymer team. And today, I'm here to kick off an hour worth of content on server-side rendering or SSR for short. I'll get the ball rolling with a brief introduction. And then Sam Lee and Trey Shugart will follow me with a couple of different approaches to server-side rendering web components. Sound good? All right, let's dive in. So over the next 10 minutes, we'll ask and answer a series of key questions about SSR. The first one being, why are we even talking about server-side rendering here at the Polymer Summit? In short, because you guys asked us to. SSR is a hot-topic in WebDev. And frankly, we've seen there's quite a bit of confusion about what exactly SSR is, why it's important, and how it relates to web components specifically. So our goal is to answer that call for information, clear up similar confusion, and let you know about some recent developments specifically related to web components. To start, let's establish what we even mean by SSR. So for the moment, I'd like to define it very broadly. We're going to say that you're doing SSR if your web server ever delivers meaningful, renderable, route-specific HTML to browsers or other user agents. So for example, given a URL like this, if your server sends something like this to a browser or a bot, then you're doing SSR. On the other hand, if you only ever send an empty HTML shell more like this, then that's not SSR. So this may seem overly broad, but stick with me, we'll get more specific soon. With that definition in mind, the next question is, why would you want to use SSR? Turns out there are two major reasons. Now, if you've been building apps for production or paying attention to public conversation on the topic, you probably know these, but let's quickly spell them out. The single biggest reason is to maximize your reach. To have any kind of impact to your app, of course, needs to have users. And the best way to reach users today are search and link sharing, both of which rely on non-browser user agents called bots. Search bots crawl the web and populate search indexes while link bots visit URLs and produce appealing visual snippets to encourage sharing. Sadly, many of these bots don't run your client-side code. If you don't serve them any meaningful HTML, your site might as well be invisible. OK, I need to pause here for a second before we move on to reason number two. Because I'd just like us to recognize how messed up it is that here in the year 2017, we're depending on services to help us find and share information that basically see the web like their browsers from 1997. Now, for anyone who embraces the idea of the web as a dynamic and capable platform, and I'm guessing there are probably a few of you on the room, I think this is an existential issue. So let's fix it, all right? OK, with that off my chest, back to our regularly scheduled talk. So the second reason you might use SSR is to maximize loading performance. Now, we all know that performance is a critical component of user experience. And in the mobile era, loading is almost certainly the most important aspect of performance. The performance-based argument for SSR is pretty simple. Serving renderable HTML is generally the fastest way to get something on screen since the browser can paint right away before loading, parsing, or executing any of your JavaScript. Makes sense, right? So now we've reviewed the two key benefits of SSR. But I'd like to look critically at each one. First, do you really need SSR for search and sharing? Honestly, this is a question you need to answer for yourself based on the nature of your site and your business. But that answer feels a bit like a cop-out. So we're just going to say, most likely, yes. Let's note the exception first, though. If you don't rely heavily on sharing, and if you're satisfied with a reach that Google Search gives you, you may not need SSR. That's because Googlebot uses a rendering service based on Chrome, and therefore sees your site very much like your users do. There is a caveat. Googlebot's version of Chrome isn't entirely up to date, and it has a few features disabled. So its rendering may differ from your users in subtle or sometimes not so subtle ways. The details are out of scope for this talk, but I encourage you to check out these resources on developer.google.com for more information. In general, though, you'll be happy to know that Googlebot runs your client-side code, fetches your data, and renders your app very much like a real browser. The problem is that Googlebot is not at all typical. As we've already mentioned, many bots don't attempt to run your code at all, and many that do do so in very limited ways. So if you care about non-Google search engines or you depend on link sharing for much of your traffic, you'll probably want to use some form of SSR. We'll see how you might do that in a minute, but first let's ask the same question about performance that we just did about search and sharing. The answer to this one is even more nuanced and frankly starts creeping into some political territory. But what the heck, I'll just say it. No. You don't need SSR to achieve excellent loading performance. Using patterns like purple, you can deliver a great loading experience without SSR. We've shown this with our own example apps and developers of real-world Polymer apps have done the same. And the Polymer version of the hacker news PWA is among the fastest to load despite not using any SSR. But while it's nice to know that you can build a fast loading app without SSR, what's more important is actually the converse. That is, using SSR is by no means a guarantee that your loading performance will be good or even adequate. So Kevin Schoff built this slide to demonstrate a problem known as the uncanny valley. SSR helps you get something on screen as quickly as possible, but if your app isn't interactive within a few seconds, your users probably aren't gonna be happy. And SSR doesn't do anything to get you interactive faster. So whether it's more important to paint quickly or get interactive quickly may depend a lot on the nature of your app, but the bottom line is that SSR should in no way be viewed as a magic bullet for loading performance. With that said, can SSR help with performance? Absolutely. So you should try hard to get interactive as quickly as possible, but for however long that takes, your users would rather be looking at meaningful content than at a blank screen. And ultimately, I think the best user experience will probably come from combining some form of SSR with a technique like purple. All right, so now we can move on and talk about SSR and web components specifically. As I mentioned in my intro, we see quite a bit of confusion about web components in SSR. And this is probably because certain features of web components do pose challenges for one very popular flavor of server-side rendering. We'll discuss what those challenges are, but the key takeaway is that web components are absolutely compatible with SSR. Let's see how, starting with a common pattern that works with virtually any form of server-side rendering. Specifically, reusable web components like UI controls and embeddable widgets can be used in any server-side rendering scheme. The same goes for a class of elements we'll call presentation components. As illustrated by this example from Electronic Arts, these are components you build yourself to standardize patterns for presentation and navigation. Each component has its own semantics and encapsulates styling and behavior to ensure consistency across your site or even a family of sites. Now, you can use presentation components in UI elements with any form of SSR. So you might craft your HTML by hand, generate it offline, server render it at runtime, whatever, you just include custom elements in your markup, being sure to place meaningful content like links, text, and images in the light DOM where bots can see it. Now, one quick note is that this pattern does lead to rendering in two stages. Your document will paint immediately, but your custom elements won't render fully until they've registered and upgraded. So it's a subtle point, but something to keep in mind. But what if you're not just integrating components into your site, but building your entire app out of web components from top to bottom? What if you don't have an existing SSR solution to lean on? In this case, you need something more. Let's look at two possibilities. One option is to delegate bot rendering to a standalone service. So let's assume you're doing something like this. User shows up, request one of your app's routes, and following the purple pattern, you serve an empty HTML shell and just enough JavaScript to handle that first route and let the browser take care of the rest. But now suppose a bot shows up and requests that same route. Before responding, you send that same HTML shell and JavaScript to a rendering service. Service returns your rendered HTML, and you pass it along to the bot and everybody's happy. So all things considered, this is probably the best way to implement SSR for a pure web components app today. The integration is light, you don't write any server-specific code, and bots and users each get what they need. Now the approach isn't new, it's been used for multiple generations of Ajax and single-page apps, but there's always room for improvement, and Sam Lee will be up on stage next to tell you about a modern, web components-friendly rendering service that he's built using Headless Chrome. Now, you may have noticed that a rendering service doesn't address performance, though, since you're only sending HTML to bots. For that reason, you might want to explore another approach called isomorphic JavaScript. This is a form of SSR in which your front-end code is explicitly designed to run on both the server and in the browser. So instead of rendering an empty shell, or returning an empty shell, you run just enough code on the server to render your initial HTML, which you then serve to both browsers and bots, along with your client-side JavaScript. Once the browser loads your code and the app boots up, it reclaims those pre-rendered DOM nodes and then runs just as if it had rendered on the client to begin with. This is super elegant, and it can be a great solution, but as always, there are trade-offs. So your code gets a bit more complicated and you end up doing more work on the server for every request. And as we mentioned, there are those couple of web component-specific challenges. First, because web components rely on web platform APIs, you need to either include a full browser in your server environment, which sounds expensive, or use an abstraction layer that provides a lighter weight implementation of those same platform APIs. And the thickness of that layer may vary depending on how many platform APIs you need to render your initial app state. Now, if your components use ShadowDOM, there's an additional wrinkle. After you build your DOM tree on the server, you need to serialize it into HTML markup. So without ShadowDOM, as in this case, it's pretty straightforward. But unfortunately, the platform doesn't currently give us any way to represent a shadow root in serialized HTML. So our simple task becomes a tricky problem. Now, there are ways to work around this limitation, but they require inserting placeholders and running a bit of client-side code during your initial render. So Trey Shugart will be on stage shortly to share his work on isomorphic JavaScript for web components and take a closer look at all of these considerations. And with that, we've wrapped up our brief intro to SSR. I hope it's been useful to you. And I'm sure that you'll be excited to see what both Sam and Trey have in store for you next. So thanks and enjoy the rest of Palmer Summit 2017.