So they asked me if I would do an advert for the Chrome Developers YouTube channel. And we thought that's too easy. So we're going to try and distract him using the ingredients we have available to us. Take it away, Paul. OK, so you can go to youtube.com.cromedevelopers and you can watch content on PWAs, performance, DevTools, find out about the content from Chrome, DevSummit, all the talks that have been going on. You can watch what's new in Chrome with Peeler Page. In the start, in the notification. There's new content every week. So don't forget to go to youtube.com.cromedevelopers and subscribe. So, yeah, subscribe, because that's a good idea and there's good content with good people. All right, all right. Is it good cake? Pretty good. I don't remember that. It was such a strange moment in my life. Anyway, welcome to day two of Chrome Dev Summit. Yes, welcome, welcome. There's some energy in the room. There is some energy. I'm wondering if they've had enough sleep and so on. Well, there's plenty of people in the room and plenty of people on the live stream. People in the room, give us a cheer, a proper one. Go on. People watching via the live stream, give us a cheer. That doesn't work. You can't do that. I like the thought of somebody in my quiet office watching and it's goo. So today has a slightly different theme to yesterday. What is today's theme? Well, yesterday was about today, whereas today is about tomorrow. What that means is that yesterday was all about what you can do today with the features that's on the web and today is more future-looking. So, you know, we're going to talk about some things from emerging and developing proposals to some new ideas. Right? You're going to talk about new ideas. That is basically what I said. But it's going to be a little bit like a round in the big web quiz because as you're watching this stuff, you get to decide whether it's like future of the web or vaporware. Right? Does that work? I think so. But we really want your feedback on this sort of stuff as well because some of it is just sort of far out there ideas and we want to know if we're going in the right direction or not. That's one of the great things about being here, right? Absolutely. So, to get us started, we need our day two keynotes and for that, we'll be inviting Nicole Sullivan and Multi-Ubil to the stage. On Twitter, they are Stubinella and Cramforce. Please welcome to the stage Nicole and Multi-Ubil. As we like to call them, Stubinforce. Hi, and welcome to the day two keynote. My name is Nicole. I'm a PM on the Chrome Web Platform team. And my name is Malte. I work on AMP and JavaScript infrastructure at Google. So, actually, this is a little bit awkward today because we're the second keynote and Ben and Dion already talked about effectively everything yesterday. So, we thought we'd do something slightly different. So, normally at a Chrome Dev Summit keynote, you know, we'd walk through all the new exciting APIs that the web platform makes available for you. And so, we actually are going to do that, but first, we want to talk about something slightly different. We want to talk about web frameworks. Developers who build for the web often choose to use a framework. In the past, changes to the web platform didn't necessarily take frameworks into account, and changes to frameworks didn't necessarily take the web platform into account. We think both the web platform and frameworks benefit from a close collaboration, and so we're out to make that happen. Obviously, if you're building something simple, it makes sense to choose simple technologies. But as soon as an app is sufficiently complex, in most cases, developers choose to use a framework. A few months ago, I put out a very, very methodologically correct Twitter poll asking people why they choose to use frameworks and got back a whole bunch of answers. And this one in particular sort of resonated with a lot of people. You can't not use a framework. Your only real choice is to either use one that's open source documented, tested, supported, maintained, mature, and proven, and I think we'd all throw, you can stack overflow stuff about it into that one. Or the option B is you cobble together some garbage, unmaintainable stuff yourself. I've made a few of those, actually. Yeah, I might have made one or two of those in my day before. And given that, we just want to start by recognizing that frameworks are part of the web, and that if you're using a framework, you are, in fact, using the platform. So let's go from there and kind of extrapolate to the further web stack that is based on that kind of insight. So on the bottom, obviously, you have the web primitive. So that would be the DOM, the Fetch API, Service Worker, stuff like that. Then above that, we have built-in modules. Built-in modules are pretty exciting. They're a new thing. It's the idea that we can build in a layered way for the web. They're high-level APIs that solve something like virtual scrolling or carousels. I think we all love to hate the carousel, but if we're truly honest, they're on almost every site in the known universe. So we can build something like a high-level API like a virtual scroller, and then that drives out the low-level APIs that we need to make those experiences accessible, searchable, truly fast. Those low-level APIs can then be used by the entire ecosystem of virtual scrollers. That makes a big difference because it allows everyone to level up together. Right. Then one level up, we get the framework. So that would be like React, Angular, Polymer, or like higher-level stuff like Next.js and Sapper that kind of treat you to everything that you need to build an application. So obviously, these aren't standardized. They're not web standards. But most applications use one of these, and so we think of them as part of the platform. The next part is web components, and you're probably thinking, wait, that doesn't make any sense. Web components are a web primitive or a web standard. I'm not talking about like the web components, the standards. I'm talking about your web components, your date picker or, I don't know, tabs. Maybe the carousel. Maybe your carousel, sorry. Yeah, these are the web components that layer on top of your stack. Why it's important to put them there is because they're an important measure of interoperability between different parts of your system. Right, to kind of make a point, let's do a quick poll here. Who here in this room has built a React application? All right, that's most hands. So if you, no, keep it up, keep it up, keep it up. If you're anywhere in your company, you also have an Angular, JQuery, Backbone, Polymer, anything like it, both hands. Yeah. So if that's the case. I love your honesty. Wouldn't it be nice if you could use the date picker in both of those? If you could have a design system that spans your entire application suit, no matter what framework it's built in. So that's where we think your leaf components, web components are really the right technology to build that. There is, however, a real problem with web development today. We're struggling to make stuff that's really fast and responsive and has buttery smooth animations.  Not everybody struggles. There are examples of sites that achieve this. But at scale, what we observe is that our performance goals aren't being met. Right. And so what we're kind of observing is that in Web Dev today, we often have to make that choice between developer experience, how we feel as developers, and user experience, how users feel. And that shouldn't really be how things are. And the vast majority of cases, developer experience combined can lead to great user experience. That's just not how it works today. But if we can achieve those things coming together, the web would be better for everyone. This is why we're so excited about frameworks. Yes, frameworks sometimes make web apps slower. That's a reality. But they're also our best hope to make them faster. Right, so that's a bold statement. It is a bold statement. To prove that this is actually happening, we thought wouldn't be nice. We celebrated all the great improvements that Framework has made through this year. Let's start over with React. They have done a bunch of foundational work. For example, they're working towards making code splitting something that's first class supported in the framework, which is really nice. And then they've done a lot of work to break up the rendering of huge dump trees into tiny chunks so that if you have a big update, it doesn't lock down your browser for like many seconds. Everything's kind of done in small breaks. This is a theme you're going to hear us talking about a few times. Yeah. Angular made improvements too. The Angular CLI enabled performance budgets. This is great because how often do you not realize that you actually alienated a bunch of users by adding that one more library or NPM installing something that didn't install a whole bunch of other things? Angular also did a bunch of work to remove unnecessary polyfills. That's fantastic. We don't want polyfills for the most modern browsers. Right. Speaking of which, Vue basically did the same thing with a thing called modern mode. So you only ship the modern code to modern browsers, right? And that's effectively the same idea. And that's why we're so excited about Frameworks, kind of bringing this best practice to all the users. Similarly with another one, just making pre-loading, prefetching something the framework does by default. Polymer did some good work this year too. They're transitioning to LitElement for super small components. And they also got faster because yay, Firefox ship native web components support. Cool. Let's talk about Svelte. They got a bullet point for already being super fast. Yeah, it's kind of hard to... With Svelte, it was like, well, they're so fast. What do we even say about this? Right. But I think this was a great example. So they built a hack and use app. And they did it in an idiomatic way. So not like using super ridiculous hacks, right? So everything in that app, HTML, CSS, JavaScript, together is under 20 kilobytes, which is just amazing. Amp did some good stuff too. So this apparently is the only feature he shipped this year because now he's a manager. Yeah, I'm sorry. So he shipped feature policies against synchronous XHR for all ads. If you're going to ship one feature, this is a pretty darn good one. Right. If you imagine, you get to put your own feature on the slide. Nice. He also reduced... Sorry, they also reduced... Yeah, reduce the JS size on the wire by 20% by enabling broadly compression algorithm. We love this kind of thing, right? Because how great is it that all you have to do is turn on a different kind of compression and you get a 20% reduction in size on the wire. Right. Moving on to Amber, which removed jQuery from the default bundle, by the way. I have a jQuery t-shirt. Just leaving that out there. Making their bundle size 20% smaller, which is great. And they did it in a way that's backward compatible so that people can slowly migrate to this. Yeah, it's pretty neat. They actually, as far as I understand, made it so that anyone could turn on and off old code using the same functionality. So that's pretty great. And then another theme here, implementing the incremental progressive rendering with batched rehydration, which, again, comes down to that chunking of work theme which we're seeing here all the time. Great. So kind of to summarize this, we really want to get to a state where not only the super experts can make great web experiences. Everyone should be able to do it. And frameworks are an integral part of making that happen. Today we feel that we, and by we, I mean browsers, framework, and tools have under-invested in tools that focus on combining great developer experience with a focus on user experience. We can make this happen as a community, but integrating the best practices, performance, into frameworks, all users of those frameworks automatically get all the benefits. And that's how we think we can achieve great outcomes for users at the scale of the web. To make this happen, we're announcing three things today. The first one is we are including frameworks in the Chrome intent-to-implement process. How many folks know about our intent-to-implement intent-to-ship stuff? A few. Great. That's awesome. So we have basically two important checkpoints. We have more than that, but two very important checkpoints when we're going to ship a new feature. One is our intent-to-implement, and the other is our intent-to-ship. At both points, when we're about to build something and we're about to ship something, we want to get a lot of feedback. And so we go through this intent process in order to intentionally go in and draw in that feedback. Previously, we had listed web developers as folks that we wanted to get feedback from, but now we're actually explicitly adding frameworks to that intent-to-implement process. Right. And secondly, we want to put real dollars behind this. So we're starting with a budget of $200,000 to kickstart developing performance-related features in frameworks. In particular, we make available a list of performance features that we'd love all frameworks to provide to the users by default. Folks who are working on a framework can ask for funding to do the actual work. We're kind of still working on the exact details, but if you're interested, check out this Bitly link for more information. The third thing that we want to do is increase collaboration between frameworks and the Chrome team. It's funny to announce this today because it's actually something that we started in the summer and we've been working with a bunch of frameworks for the past several months. But we're excited today to talk through some of what we've started already. Right. That brings us to our next section. It's very much under construction. You heard that in the intro today. What we're hearing about here, these aren't things that are shipping tomorrow. Some of them you can try out a little bit. Some of them are like... Some behind the flag. Yeah. We're like really just thinking about them. So it's still very much time to give us your feedback, your use cases, your examples to kind of work out how they really work. The first one we want to talk about is display locking. We basically don't want to update the DOM inadvertently, and so this gives us a way to lock it. Before I joined Google, well, many times, I think this is one of the most requested features.  The idea of display locking is that you can basically lock down a section of your DOM and we won't trigger render and other things on that bit of DOM until you unlock it and say, okay, it's ready to go. It's super subtle, and it may not be something you interact with directly, but it's definitely something that frameworks need in order to eliminate unnecessary browser work. Now we're collaborating with the React team to nail down the API, and we had an intent to implement out about a month ago. So if you have comments, we'd love to hear them. I have a question, though. Is it related to that BG color? Because I'm using that every day. Ready? Absolutely. Nice. Well, this is kind of awkward. Is it working? I don't know. It's kind of strange, right, to see a blank white screen in the middle of a presentation. Why do we think that's okay when web pages are loading? Sort of, ah, what's going on? Right, every time, every single time you load a new web page, the browser says, hmm, what's the good idea to do? Oh, yeah, I'm going to paint white, and then it's going to take a while, right? Why is that the case? So it shouldn't be the case. We should tell you that we totally scared the tech check people when we had a blank white screen during our tech check. All right, we really need page transitions on the web. You're probably familiar with stuff like this from the material design specification, right, or one page morphs to the other, and there's other ideas how to do this. Now, this is something you would see in your application going from one state to another. But we also want this for normal navigations, right? Like, here's a great example. So this is something the image search team at Google was working on. It's kind of subtle, so... Yeah, we'll walk you through it. So this is their image search result page, and when you click one of the images, you go into this light box, right, just to see the larger version of the image. So their goal was that more people click through to the underlying web page, and so they wanted to make that really easy by just literally putting that web page at the bottom of the page, right? So that, as a user, all you have to do is, you know, put your finger on it, and kind of draw it up, right? We're hoping that this greatly creates... increases the number of navigations actually happening, but this is something that you really just can't build on the web today. We'd love for you to be thinking, like, if you didn't have to have that blank white screen, what would you build? What would you design? Because I think it's actually pretty exciting a space. Right, today, you really have to choose between either a fancy transition or doing a real navigation with a browser load on your page. And there isn't really a solution for the cross-origin case where you navigate to a different domain at all. And so that's why we're so excited about portals. What portals give you are advanced transitions between websites that are real navigations, spas, single-page apps, right? That's the way to do it today. But here you can, and this is what this example gift shows, this is a navigation from one web page to another, and you can morph between them any way you like, which seems like something we should have in 2018. It does, doesn't it? Yeah, I think sometimes we will choose a single-page app with all of its complexity when actually what they wanted was fancy transitions. Right, it can't be really hard to do a single-page app. Cool. So I got a sporty new car, and within a month, I got a ticket. I was driving too fast. In Germany, hopefully. No, on the San Mateo Bridge. Oops. I won't tell you how fast I was going, but I found out that my car has this really cool feature. I can turn something on so that it beeps any time I go over 80 miles per hour. That seems really good because there should be limits and this car does not feel like it's going fast when it's going actually pretty fast. There's also something you can turn on for a motor or a car, which is called a governor, which actually will not allow the car to go over a certain speed. Feature policies are sort of like that. You have a couple of options. You have enforce mode and you have report-only mode. You can turn a feature policy on for something like synchronous XHR and you can say, nope, I don't want to allow that and it simply will not allow that to happen on your site at all anymore. Or you can turn on report-only mode and you get that beep, you know, hey, something's wrong, you should check it out. We're pretty excited about feature policies because they run in CI, you can run them in development, you can run a different set of feature policies on your third-party content, your ad content, then you do on your regular page. So you've got a lot of flexibility around how you use it and we're excited to see what you want to do with it. What you can use today is a synchronous XHR feature policy. We collaborated with the AMP team and they've got it turned on for all ads in AMP, which is pretty exciting. It's basically, by the way, the worst feature on the web. You want to turn this up for your website, right? There's no good reason to have SyncHR. There's basically no conversation in which Malta does not bring up that you should turn off synchronous XHR, even at your barbecues. There are other policies that are available as well. So there are some exciting ones, but they're behind a flag. So you have to go and turn it on behind the flag in order to check it out. There are three I'd love for you to look at, unoptimized images, oversized images, and unsized media.  We would love more feedback. And don't upload pictures from a DSLR directly to the web. Yes. And you'll hear Jason talk more about this a little later today. Right. All right. Next, we want to talk about instant loading. So how we get from super fast to zero milliseconds to kind of show you what exactly we mean by that because instant is an overloaded word, right? There's instant apps which don't do instant stuff. So let's talk about this. Here's a film strip you might be familiar with from like Webpages or called Webpage Loads. This one loads in eight seconds, right? And obviously you could make that faster. And we've spent years trying to like eke out every little second that we can out of the film strip, right? Right. But we want this. We want basically everything go away and only that last frame to render right away. So we have a solution for that, which is actually relatively obvious. We have to like load that web page before the user clicks. But now you might wonder why I put a bathroom stall on the screen, right? So US bathroom stall has this little gap which, like this, introduces a privacy problem, right? Does anyone know why it's the case? Anyway, so when you load some other web page, before the user said they wanted to go there, that web page might be able to like read your cookies, set cookies, stuff like that. And that's not something user expects, right? So we need a solution for that. And the solution that has been under development for a while is called web packaging. What it kind of provides, as one of its features, is privacy-preserving instant loading for the web. I want to explain really quick how that works, but we'll have a talk later today that goes into like actual detail from people who are working on it, which is great. So the way web packaging works is that you're a document author and you have a TLS certificate that we're using for HTTPS, something like that. And you sign that content to be created by you and then anyone can deliver it on your behalf, but the browser says, okay, this was originally signed with that TLS key. So I can say it came from like example.com because that was the original party. And I want to kind of drill down on this, anyone can deliver it. So you could have a different CDN, but you can deliver it over like BitTorrent or IPFS. Doesn't really matter. You can do basically HTTP over anything, which is really cool. So we collaborated with the AMP team on this because they're one of the frameworks that we're working with. And we're pretty excited about the instant loading and how fast we're going to be able to bring content to users. But Malta, what about the URLs? Yeah, AMP doesn't have very good URLs. So they're startwithgoogle.com. And with web packaging, that problem goes away, which is really cool. So that's why we excited about it. But, and this is the important part. It's a web standard. And so with web packaging, we can bring instant loading to all these frameworks. And this is not an exhaustive list. It doesn't really matter. This technology is completely technology except, doesn't care about technology. So really, really cool. We can't wait for this to land on browsers. Web packaging also addresses one more problem that I think is really subtle. Eric Meyer treated this and wrote this blog post, which is really cool a while ago. Traveling to Africa and noticing that, you know, HTTPS, which is the greatest thing happened to the web in a while among many other greatest things, actually introduced a few problems.  It's great if you have an edge cache at that cell tower. Now with HTTP, that's something you can build. With HTTPS, it's something you can't build. So you always have to go to the origin to someone actually able to surf on that TLS certificate, right? And the great thing about web packaging is that it can bring back that feature, right? Because it's untangling delivery from TLS security, you can get that all great benefit of having edge caching for HTTP, but have it together with the security benefits of TLS. I also wanted to just really quickly say that web packaging is not related to Webpack. However, there is a bundling spec coming up, right? And so web packaging is actually going to bring bundling as a first class feature to the web platform, which I think is also way overdue, and so bundlers like Webpack can eventually use web packaging as the output format. You can actually try this today. There's a subspec called Sign Exchange, which is available in Origin Trial. You can go to this URL and try it out. Let us know what you think. Yeah. Later today you'll hear Kanoko and who else is speaking about? Yes. So the next bit that we'd like to talk to you about is scheduling. So anytime developers build something sufficiently complex, they end up needing to manage a task queue, prioritize work, and be sure that everything is getting done on time. So we don't run out of time on our talk? That too. A typical app has competing deadlines, so keeping the user input responsive while rendering smoothly at 60 frames per second and doing the actual work of fetching, preparing, and rendering the UI. In talking to the React team a few months ago, we realized that a framework-based scheduler has serious downsides. It can't schedule third-party code. It has a lot of difficulty interleaving tasks with browser functions like rendering and garbage collection. In short, it has to fight other systems for resources. With help from React, Google Maps, AMP, Polymer, and Ember, as well as the Web Standards community, Shuby and Jason, who you're going to hear from later today, are designing a scheduler that will run in the browser. It's meant to have high- and low-level APIs like Grand Central Dispatch, so borrowing some ideas there, and be able to interleave code from all different sources. They're working on things like, how do you interleave garbage collection or code that's in a promise? What's exciting about this in particular is that when you break things down into small tasks, it's much more useful if you have a great way to schedule them. When you can schedule things, they're much more valuable if you've broken things down into small tasks. This is where frameworks and the browser can work well together to provide a much better user experience than we're capable of providing today. This is one of the things I'm most excited to PM right now, and I'm really excited for you to hear from Shuby and Jason later. It's really a good example for how frameworks help because actually taking your code and breaking it down into small chunks, that's really, really difficult. But as a framework layer, this is something that people can just take a long time doing, but then having it for everyone. I mean, I think you saw in the framework award section earlier that three frameworks, at least, are working on breaking things down into really tiny rendering chunks. So this is pretty exciting. Right. Next, we're talking about Animation Workflat and Jankfree Pal X.  So, Animation Workflat. First, we need to talk about other animation APIs because there are a few. There's the Web Animation API, which is great, and you should use it. And also, more importantly, it just landed in Safari Preview. So relatively soon, we should have it in most browsers. CSS animations are also awesome, and they're basically everywhere, so you can use them. And you should use these APIs. And Animation Workflat doesn't provide additional value except in some very important circumstances because these APIs are inherently time-based, which makes sense, right? Animations go from A to B over time. That's kind of what they do. However, there are some animations that aren't time-based. For example, this one, which animates Pac-Man based on scrolling left and right, right? And this is something that's really difficult to do on the Web today in a jank-free fashion. And then, so the reason for this is that with Animation Workflat, on the other hand, where you don't get jankers because that actual Workflat runs super close to the actual software that does the scrolling. And so you can do it even when the main thread does anything busy, right, which is really cool. My team actually has been working on getting this into what we call scrollbot animations, and it was just a drop in a replace and it makes everything so much smoother. Surma is talking about this later today and the talk about Houdini. And he'll have some really cool demos. Yeah. Almost every Web app eventually needs something like an infinite list. It just happens, right? On other systems, on Android, on iOS, there are things like UITableView. On the Web, you're sort of left to figure it out yourself. Now, many frameworks have really good implementations of a virtual list, an infinite scroller kind of situation. But the Web platform primitives make certain behaviors impossible. For example, have you tried to use Find in Page if you're using an infinite list? I often find myself going back to search for a tweet that I made or someone else made some time ago. You can't search for things that aren't actually in the DOM right then. This is obviously going to have accessibility implications as well. With new low-level APIs that we're putting into place, like searchable and visible DOM, all of the sudden these things become solvable and get addressed. You'll hear more about our collaborations with React Virtualized, Angular, and Twitter in Gray's talk a little later today. All right, so that kind of brings us to the end of our talk, just kind of summarizing. We have been talking about our vision for a framework-inclusive Web platform future. Instant loading and page transitions are coming to the Web, especially if your designer gets thinking about what you're going to build with that because it's going to be kind of cool. Right, and then we talked about a set of new low-level APIs making it easier to build reliably fast Web apps. And that's especially true if frameworks help Web developers take advantage of them by default. Thank you very much. Thank you. Day two means more big Web quiz, if I can get those words out. Yeah, good luck with your talk later if that's how you were going. Very awkward. Yeah, so let's get the big Web quiz on the screen so we're going to play another round. Actually, before we do that, can I play the intro video again? You mean my intro that you then ruined? Yeah. Yeah, go on then. Yeah, can I play it? Yeah, go on. Yeah, yeah. Here we go. It wasn't supposed to actually break it. I'm going to stop that. That wasn't actually intentional. It just actually broke. I don't think I know why. Just before we came out here, Serma ran up to us and went, ah, just on a deploy, I've changed the presentation view and I think that's exactly what it's done. I think it broke that. Perfect. Marvelous. Ah, because one of the things he added was polling. Polling every second. This is live debugging. And that's what's happening right now. That's exciting, isn't it? Well, at least we know that the polling is working. Brilliant, excellent. This is going to go really, really badly. So because it's day two, and just to remind you, the prize that is up for grabs. Use it to wow your colleagues and scare your pets. Ooh.  You know, just saying that. So just so you know. I don't want to press this button because I don't know what's going to happen. Let's find out. Let's find out. I hope you've signed into bigwebquiz.com and you're ready to go. Let's go. Let's find out. OK. Let's see how it works. The question. Here it comes. Maybe. Please. Come on. Something changed on the screen. Or not. Shall we roll back the deploy that we did earlier? I think that might be wise. Yeah. This feels like two years ago when we had a total failure on the login system, doesn't it? At least it's me and you. Right. You know, we didn't take anybody else down with us. Let's abandon that and figure it out. Do you want to introduce the next person? I do. It's Jason Chase. Ladies and gentlemen, Jason Chase. Round of applause. Good morning, everyone. I'm one of the Jason's that you'll be hearing from. I'm not doing as many talks as they said. So I lead a Chrome team whose mission is to help developers better understand and control the web platform. So we've been working on feature policy and reporting API, which we think can really make your lives easier as web developers. Maybe we won't save you from speeding tickets like Nicole said, but we'll see what we can do. So we know there's many benefits to being on the web, but as a development platform, it's far from perfect. On the Chrome team, we regularly provide web consults to help people address issues with their site. Now, these consults bring together developer relations, engineering, and other folks to help people deep dive into questions or issues with their site. Now, the goal is to provide actionable recommendations to improve things. Now, as a result, we've identified common mistakes that happen over and over again. And spoiler alert, performance is a common theme here. And the two big performance problems we see are too much script and too many image bytes being sent over the network. So you know there's a right way to do things, but it's adventure to find that sometimes. And even if you find the right way, there's bumps, or you might slip off the path. So as we've seen in other talks, there's a long list of things to keep track of and get right. Now, this is hard enough if you're an expert developer, but imagine you have a dev team with junior developers and you need to keep everyone on the same page. So we need help. What if we could make web development easier with guardrails? So if you imagine guardrails along a path, if you hit a rail, you know you're doing something wrong. And the rails stop you from leaving the path. Now, this isn't necessarily a new idea, but looking at repeated mistakes in our web consults, we're thinking about different ways to apply this. Concretely, how could we help you put guardrails in place for development? So AMP gives us examples, an example of guardrails and web development. AMP gives guarantees you're not going to be off course by making it nearly impossible to do things wrong. Now, AMP started by providing building blocks, tightly constrained to ensure great performance in UX. So this is an opinionated approach to carve off good parts of the web platform. Now, not everyone can or wants to use AMP. So learning from AMP, we thought about a more configurable approach. And that's feature policy. So we're really excited about it. We think it's going to be great to help guide you towards the well-lit path of web development. Now, with feature policy, you opt into a set of policies for the browser to enforce throughout your site. These policies restrict which features the site can access or modify the browser's default behavior for certain features. So let's talk through some of the common problems we've seen. So images often have extra quality or metadata that take up space but isn't required. Now, as we've seen in other talks of web, again, there's many tools to optimize images. We have to remember to use them or you have to integrate them into your build pipeline. Now, ideally, your page should never serve images that are larger than the version that's rendered on screen. Anything larger just results in wasted bytes and slows down page load time. So a common example might be sending a desktop-sized hero image to a mobile device. We've designed policies to catch common mistakes of unoptimized or oversized images. So we researched the impact that we think these policies can have on 10,000 most popular sites. Our analysis shows that 10% of sites can save over 500 kilobytes on average. Now, that can reduce load time by up to three seconds, sorry, 10 seconds, on a 3G network. So let's take a quick look. So this shows the policies being applied to a site. Now, on the left, policy for unoptimized images is turned off and you can see the image is loaded normal. On the right, we've turned on the policy and it's blocked one of the images. So we compute a compression ratio of bytes to pixels and if that ratio is greater than 0.5, we'll block the image and we'll show a placeholder. So the idea is to point out the images that need to be corrected. So this site might look familiar. You know, at Google, we're big believers in dogfooding so we went and applied all the policies we could to the site. Lo and behold, we found out we made a few mistakes.  Just shows that even the experts, like our developer relations team, can make mistakes and so we really need better tooling to help catch these kind of things. So another common problem is images without explicit sizes. Now as we see on the left, this can cause a user experience to jump around as a browser loads in new images and resizes a page. Now on the right, we've applied a policy to catch this. So the browser can set these images to a fixed size and it'll keep your user experience stable. So how does this all work? Policies, like I said before, are a contract between developer and browser. We use them to inform the browser about our intent for our site. It's a set of rules for how each page should behave. Now the browser helps keep us honest when our page tries to veer off the path by validating that it's behaving according to its stated rules. So if a page or embedded third-party content attempts to violate any of the rules, the browser will identify or block the behavior and in some cases, it may override the behavior to provide a better user experience. All right, let's take a look at how you configure policies. Now each policy refers to a single feature and then it defines a list of origins that are allowed to use the feature. Now with each page response, you can add this feature policy HTTP header. So in this example here, this will catch all oversized images and this is the one that saved our bacon on the CDS site. Now here, the non-keyword means that no origin is allowed to use the feature of oversized images, disabling it entirely for your site. Now looking at that example, you might wonder why we would say oversized images are a feature. Now we have policies for helping you enforce best practices to ensure good performance in user experience and the way these often work is we'll define a known bad practice as a feature and then you use the policy to prevent it. Now we do this for web-compatible reasons. We don't want to go ahead and break the internet by all of a sudden turning off oversized images for everyone. So we'll allow that behavior by default and then you opt in to turn it off. Now this header applies a policy that catches any images that are not optimized. Now here we're making an explicit exception for our photo CDN. Now in this case it might be because our users expect really high detail glossy pictures and those, excuse me, those don't compress well. Now in this case there's only one origin listed and all origins will not be allowed. So here's an example that puts them all together. So first we have a policy that ensures every image has explicit dimensions. So we saw this earlier preventing your user experience from jumping around. Now second, we have a policy to selectively enable the geolocation feature. So now we're applying this to our own origin and to our trusted maps provider. The self keyword here means the origin of the top level page. So by combining this with explicit origins you have full control over who's allowed to use a feature. And then finally we're allowing any origin to use autoplay. And here you see an asterisk keyword. That means essentially everyone. So by default Chrome will only allow autoplay on same origin iframes. With this policy we can allow cross origin iframes to play as well. So in that last example we saw features in the more traditional sense. You know well-known APIs that are exposed to the web like geolocation, camera, full screen autoplay. So before we saw policies about enforcing best practices. So now we have policies that give you granular control over the features you use. So we've probably all seen this example.  So with feature policy you can lock this down to either prevent the use of the feature at all or really just dole it out to specific origins you trust. So we've talked through some examples of an HTTP header. You can also use an allow attribute to control feature policy on iframes. So now why might you want to do this? Well as we talked about you can be really selective. So maybe you have one frame on your site that shows a map. You could use the allow attribute to grant the geolocation usage to that frame and on no other frames. Now in the example we see here this allow attribute is changing the default for the autoplay feature. Well you'll notice if you go to generate an embed on YouTube they're already using this in production today. So we've seen a lot of flexibility in how you can configure feature policy. So we've built in some rules to make sure they're being applied correctly. So multi in the keynote talk rather enthusiastically about not using syntax HR. And yes we do have a policy for that and AMP is using that in production. So the way the rules apply is first policies are inherited. So scripts will inherit the policy of their containing frame. So this means that for your top level scripts they'll inherit the policies of the main document. So this means you can apply the policies at the top and they cascade down to all nested subframes. So in AMP's case they can set the policy to disable sync XHR and know that it will be applied to all subframes regardless of how far they might be nested. And this applies to the allow attribute as well. So if you have an allow attribute and you have a header the stricter of the poo policies wins. Now on the other hand we have this one way toggle. So disabling a feature turns it off permanently. So that means again in AMP's case they've turned off the feature with the sync XHR policy and that means no frame nested or otherwise can turn it back on. Now for policy supporting best practices it might not be feasible for the browser to actually block the bad practice before it occurs. It can only detect the problem in some cases and then break your page in an obvious way or notify you. The goal in that case is really to let you know there's a problem to fix. Now we saw this in the policy for an optimized images and oversized images. Now in other cases the browser can actually block the bad practice so your site continues to behave well. The policy for unsized media works this way. So it'll apply a fixed size to images to prevent the user experience from jumping around. So we have DevTools and Lighthouse to give you great insight into the behavior of your site. So where does feature policy fit into your development workflow? Feature policy lets you set the policies up front and then catch problems early during development before anyone writes a lot of code. Now you can build policies as defaults for new sites or new pages and this way you can enforce standards across your Dev team. Policies are served with each page and validated at runtime so you can choose to turn them on for some users and not others. You can also turn them on for some pages in your site and not others as you incrementally improve your site, for example. So at a minimum we recommend enabling the policies on your staging server. This can let you catch problems that you didn't see during development.  So this can catch problems with that. In addition to staging, you can also apply policies and production. You can have your Dev team, your managers, all the way up to your CEO use your site with policies enabled so that you can find real issues in the wild. For regular production users, you likely won't enable the policies if violations will break the user experience. So for example, with the image policies loading unoptimized images more slowly, it's probably a better experience than having them missing altogether. You still want to know about all these violations so you can correct them. So we've designed report-only mode to give you the best of both worlds. So you can configure policies similar to the examples we saw before, but you mark them as report-only. So you see here, internal users, they have the policies enabled, right? We'll break things, we'll see problems with images that need to get corrected. For production users, we have them report-only mode so the production users get the normal experience, but then you can get reports about what's gone wrong. So speaking of reporting, feature policy violations are really just the start. There's lots of other info from the wild that would be really valuable. So for example, browser interventions. Sometimes a browser needs to intervene to improve the experience for the end user. So an example of such an intervention is blocking document.write on 2G connections. So there we've discovered that doing a document.write on a really slow connection can really impair the user experience. So to protect that, we've just blocked it. But that happens in the wild, you don't know about it. You really want to find out about it so you can correct it. Now what else? So just taking a look at this, there's lots of things going on in the wild that you'd really love to know about. Now a problem, some of these are just console messages which you can't collect. Now there's other things that have a bespoke API like window.onair, so you kind of have to remember to go hook up something there to get some errors. And then there's things like crashes and network errors that just aren't possible to capture from script. So the solution here is the reporting API.  So one stop shot. It exposes information that wasn't available before. We've talked about like network errors, crashes, now that's coming soon, feature policy violations, right? Deplications, interventions and network errors, you can get those today for the reporting API. There's two ways to use the reporting. We have the reporting observer which lets you collect reports client side with a JS API. Now you can filter by report type. Here we've said we just care about deprecations and feature policy violations. And then you can use the callback to funnel these reports to your own analytics provider or however you'd like to capture them. Now because this client side, the available types are limited, but the key feature here is it buffers results so you can set up your reporting observer later and still get reports that happened earlier in page load. So every report has some common fields so we can see here the type of the report and the URL where the report happened. And then for each report type, there's a specific body. Now for feature policy violations, we see it's telling you the feature that you're using and it tells you where in your code the violation occurred. Now the second way to use reporting is with the report to response header. So this lets you configure out of band delivery of reports. The browser will queue up reports and send them to the location you're choosing separate from the execution of your page. And so here you can get all of the report types that we saw earlier. So you'll see a couple fields here. So first there's group and that just lets you name this particular set of end points. And then you can refer to that group name in other parts of your configuration. Now max age says how long this configuration is valid for. After that, we'll throw away this configuration. So this lets you, you know, change end points over time and gradually switch to new ones. And finally end points is an array of URLs. So you can configure multiple URLs for fallback. So if the browser can't reach one endpoint, it'll try another. And so talking about one place to configure reporting, CSP, content security policy, now integrates with the reporting API. So whereas before, you'd specify a report URI and you'd give it an URL to where you wanted your reports to go. Now you can use report to directive and you just point it at one of the end points you'd previously configured. So if we go back to the previous example, you'd send a report to header and you define a group called CSP endpoint. You can have all the URLs you need there, the age, and then you just refer back to it here. So where can you use this stuff? So both a feature policy framework and the reporting API are shipped in Chrome. Firefox is implementing feature policy and Safari has support for the iframe allow attribute. Now, what's really great is you can benefit from using these policies now, even though there isn't broad support across browsers. If you do some of your local testing in Chrome with flags enabled, you can apply all these policies and catch problems before they reach other environments. So I've talked a lot about a few policies. You know, walk through the examples, depending on why you might want to use them, but that's really just the start. So here's a list of all the ones we have available today. Most of the ones around granular control, like turning on and off features like geolocation, microphone, those kind of things, those are already shipped, so you can use those now. And we saw that with the YouTube example and with AMP. A lot of the best practice policies, those are behind the flag, and we're also working on a bunch more. Now, seeing that long list, how am I going to set up policies? How am I going to try them all out? Well, we have a handy DevTools extension. So this lets you really easily toggle a policy on and off and see the effect on your page. So you don't have to configure to set up headers or modify your code to allow attributes. You can just try it and see what will happen. So here we've seen an example of using the extension to turn off the geolocation feature. Now, this extension uses a JavaScript API. So the advantage there is you can feature detect which policies are even supported, and you can go one step further, and you can query to see which policies are enabled or disabled. So this can allow you to code defensively. So, for example, if you have content that's embedded, you can respond differently if you know the feature isn't available to you. So we really love to hear if these policies are useful for you. The ones we're really interested in are some around some of the images and even sync X-ray chart. We made it easy for you to hopefully copy and paste and get a header sent real quick. Now, if you have ideas for new policies or if you have feedback on the existing ones, we'd love to hear from you on our GitHub repo. And finally, you can head over to featurepolicy.rocks, and you'll get more information about feature policy, about code samples, and live demos. Thanks a lot. Why, Jake, would you like to try the quiz? I would, Paul. Shall we get the quiz on the screen? Wow, I wonder if that intro would be good to see again. I will press the intro button, and this time it will play all the way through. Thank you. Come on. Please. Oh. Two. Brilliant. OK, it feels like it's working again. Yes. OK, so get your phones out. Remember, laptop's out. Yeah. The set of questions today are if it could be... Oh, I'll press the button first. There you go. TLDs? Yeah. So we're going to be asking whether the TLDs that you're shown are valid TLDs, top-level domains. That little bit at the end of the domain name, right? Like .rocks.com. Yeah, and there's loads of them now. There's loads.  That's a good point. Let's start around. It is a finite list. We've got three seconds per question this time, hopefully to give you a bit more time for some people saying it was a little bit too quick yesterday. So what have we got here? Purple, brown, Washington, Vegas. Oh, some city names. OK. Yeah, some of those may be real. New York, black, white, Berlin. Oh. Confidence is just fluctuating wildly on these. It would be really unfair if some of the, like, cities and countries were OK and some of them weren't. That would be awkward, wouldn't it? They wouldn't have done that, would they? Let's find out. Oh, it's .San Francisco. Relevant. Topical. Very little confidence. That means people are voting roughly 50-50. Interesting. Ah, now that's how it's panned out. Let's have a look then. There we go. Back at the start there. Back at the start. There we go. Purple, brown. It's pretty evenly split, I would say that, Jake. Yeah, pretty confident Vegas is one. Shall we see what the answers are? Yeah. Here we go. Oh, so they were all fake except for Vegas. OK, so Washington fake, Vegas. Real. OK, fair enough. OK. Next set. What have we got here? Can I just remark on the fact that there's pretty much a 50-50 split? Yeah, I would have been exactly the same. Exactly, exactly. What are these ones? Oh, OK, so New York is fake. Berlin, all good to go. Oh, so we've got black but not white. And Berlin is one as well. OK, fair enough. Let's have a look at the next set. Teal, these are odd. Again, just 50-50. I want to see the San Francisco one. Oh, yeah. Is the home city represented? It is not. It is not. It's not. It's not. In all love in the room for San Francisco, right. And the last set we have here. Dot Jake. Yeah. Dot Jake. Yeah. Fake. No, it's fake. Yeah, that's a fake one. That's a relief, frankly. Honestly, if Rome is not getting in there, Jake is not getting in there. All right. I'm calling it now. That is a fair comment. Well, isn't it nice that it worked? Slight relief. Right. It's time for a break. We'll be back in here at 11.30. See you then. We're going to do another one of our HTTP203 microtask speedruns, right? Yes. Oh, no, it's microtask speedruns. Oh, I don't know. We are not going to branding, mate. I think microtask is a good branding for it, right? Yeah. Because the idea is you're going to explain a thing in two minutes. Broadcast channel. Broadcast channel. Yeah. Okay. Oh, hang on. Broadcast is a WebRTC. No. No, no, no, no. We're in a different area. It's in the API. It also has been around for quite a time, similar to workers, but it doesn't have as wide support, sadly, because it's not been used a lot, but it's really cool. So it was a type of worker? No, but it has to do with workers in a way. So a broadcast channel is basically a post message channel associated with a name. So I can say new broadcast channel, Soma. And now I get a post message endpoint for the name Soma. And every other site, every other realm from my origin, like my workers, my service worker, all the other tabs that are open from my site, can now communicate through this same message channel because they know the same name. So it's like pubs up? Yes. Across tabs? Yes. And you have to worry about knowing which tabs are open. Do I have a service worker? How many workers are there? It just works. And that is brilliant because what it allows you to do is to write little pieces of code, little modules, that just hook up to this broadcast channel and start working. So previously you would have to use shared workers to be the sort of middleman for all of this? And have some kind of management unit. So this module is now here. Do you want to talk to it? And now you just have the central unit in the platform. And whenever a module is finished loading, it just hooks itself up to the thing. And now you can talk to it. And that is absolutely amazing. I have recently discovered for code splitting because you just load things whenever you need and they just start working. You don't have to actually statically import. You just dynamically import. So what kind of messages are you sending through this then? So I have like a cache manager in there. I have things that do my color scheme adjustments, my animator. All these things are now just like little, tiny independent JavaScript modules. And they use broadcast channel to talk to a worker, to my main thread. So one page receives an update and it can just tell all the times, I've got this data. You don't need to go and refetch it. Yeah. Brilliant. And what browsers? No. Go to my Firefox. Brilliant. There we go. I like that you knew that. Let's do another round of quiz. Big web quiz again. Yeah. Yesterday we had CSS colors. Yes. I thought it was so successful and there were so many good ones. Yes. We should have like revenge of the CSS colors. So we're going to go again. You ready? Ready? Yeah. We're getting ready to go for it. Part two. Part two. On your marks. Get set. Go. Go. Lavender blush. I like this three letter word, like medium spring green. Pale violet red marvelous. Fire brick. Honeydew. I feel like that should be a real one. Honeydew should be. Yeah. Yeah. I can see that. I mean, it's a color. Medium hot pink. I love a good hot pink. Yes. But I'm not sure if medium hot pink is a real one. This implies that there is a level of pinks. Right? Yeah. Transparent green. I'm not even sure how that works, honestly. But it could be there. Yeah. Or could it? Ooh. Ooh. Any closing? Here we go. Any second now. Ooh. Yeah. Not surprising, I think. I mean, again, looking at this list, I think I was very confused as to which one of these... Yes. ...which one of these lot was real or not. Yeah. And in fact, they're all... Everything is real. They're all real in that block. But do you believe it? Yeah, you would. Oh. You probably would. Everyone is pretty confident about this. Yeah. Yeah. Do you really...  Yes, I do. You know your CSS colors. Yes. Yes. Interesting. Ooh. Ooh. Or on the fake side now. Yeah. It's all fake. Yeah. Wow. This crowd is, again, getting wiser to our charm. Space gray. Mm. Confident. Space gray, real, interesting. It is not. It's all fake. I heard the sigh there before it came up. Ah! I'm so disappointed in myself. Don't be. These are so silly. Yep. The point is to be silly. Exactly. So it's time for our next speaker, who's called Gray. A valid CSS color and also an excellent human. Yeah. Ladies and gentlemen, Gray Norton. Good morning, everyone, and welcome back from the break. It's true my name is Gray. And I don't think my parents could have known when they named me all those years ago that my hair would prematurely match my name or that I would be a valid CSS color. So I give them a lot of credit. So I'm the engineering manager for the Polymer project at Chrome. And my team focuses mainly on web components and libraries and tools to help you use them. But we're involved in some other stuff, too. And today I'm here to talk about something a little different. Or maybe we'll just stand here and look at my picture. So shockingly, we're going to be talking about performance. As you may have noticed, we're a wee bit obsessed with that topic. And by now, you've already heard about speed tooling and best practices for doing everything faster from loading to rendering to responding to user input. But for the next half hour, we're going to drill in on something a little more specific. And that's a proven pattern for improving performance that we'd like to see more of on the web. Ben and Dion mentioned in yesterday's keynote that today's web platform is really a high performance machine. It's way faster in almost every way than it was even a few years ago. But there are still some surefire ways to slow it down. And one of those ways is just trying to render too much. Especially on low-end mobile devices, you can bring performance to a crawl by piling on too much DOM. And sadly, there are key parts of the rendering process, like styling and layout, that just take longer the more nodes you have in your page. So for a certain class of performance problems, the best thing you can do to speed things up is to lighten your load, minimize the number of DOM nodes you have in the page at any given time. And there are various ways to do this, of course. But one of the simplest and most effective is to adopt a pattern called virtual scrolling. So for the last several months, a couple of members of my team have teamed up with some of our Chrome colleagues and some other folks inside and outside of Google to explore what it might look like to add first-class virtual scrolling support to the web platform. Today, I'd like to share what we've come up with so far. It's early, but we're pretty excited about where the project is headed. We'll start with a quick introduction to what virtual scrolling is and how it's currently being used on and off the web. And then we'll take a closer look at the performance problems we're trying to address, seeing firsthand how too much DOM can impact the responsiveness of your pages. Next, we'll talk briefly about the approach we're taking. And we'll show you what we've come up with so far. And then finally, we'll look ahead to what's next and how you can get involved if you're interested. So without further ado, let's see what virtual scrolling is all about. For the sake of comparison, first we'll look at ordinary scrolling. So the blue box here is our viewport. And as you can see, as we scroll, the document moves behind the viewport, revealing content further up or down. But notice that all the content was present from the start. The only thing that changes is what we see. Now, here's the same page in a virtual scroller. As you'll see, only part of the content exists in the document. As we scroll, nodes are dynamically added and removed, keeping just enough to fill the viewport. And this is an obvious one at load time, since we only need to render one screenful. But as we'll see, virtual scrolling actually also improves performance in other ways that might not be as obvious. So when does it make sense to use virtual scrolling? It's clearly a natural fit for any time you need to display a lot of data in a list or table form, for example, like this address book. And also, it's an obvious call for content feeds, obviously in cases like social media or messaging. But feeds have started showing up in less traditional places, too. So some publishers have started stitching together articles in a way that takes advantage of the low friction of scrolling. And this may not look like your garden variety infinite list, but nonetheless, it's absolutely a case where virtual scrolling can help. And for that matter, we actually think there's a strong argument to be made for looking at virtual scrolling in cases beyond lists and feeds. A single piece of long form content, like this Wikipedia article, might easily contain tens of thousands of nodes. And the same techniques that we use for lists can also help us keep the weight of documents like this under control. So virtual scrolling isn't a new idea, of course. It's widely used on native mobile platforms. And in fact, both iOS and Android put virtualized views front and center in their SDKs, making this one of the first concepts you learn as a new developer on one of those platforms. And this is a big part of why native mobile apps tend to feel fast. A basic native view is actually heavier than the equivalent chunk of DOM, but the mainstream use of virtual scrolling on platforms like these helps keep performance in line. Now, you might be thinking, virtual scrolling isn't new to the web either, and you'd be right. This is an effective virtual scrolling solutions for all of the top frameworks, including, among others, React Virtualized and its younger sibling, React Window, the Virtual Scroll Viewport in the Angular Material CDK, and the View Virtual Scroller Library. But these solutions are currently getting by without much help from the web platform. So in the age-old tradition of paving cow paths, we asked ourselves, what might it look like for the web to have a fast virtual scrolling support? How could we make things better? And we came up with a few ideas. First, virtualization generally means you can't link to locations within the same document, since the browser can't scroll to a node that's not currently in the DOM. Now, this may not be an issue for many use cases. You don't see a lot of links between address book entries, for example. But in other cases, it is a big deal, and it breaks a fundamental feature of the web. And there's a similar problem with the browser's feature, which only sees text if it's present in the DOM. And then there's search friendliness. Since virtualized content is added on the fly, it's not generally visible to search engine crawlers. And again, this isn't relevant for every use case, but we'd love to get the performance benefits of virtual scrolling without sacrificing indexability. Finally, and maybe most importantly, we'd like to see if we can greatly increase the amount of virtualization that happens on the web by adding platform level support. While you can do it today, virtual scrolling on the web is basically a fringe feature. You have to discover you need it, and then you have to jump through some hoops to get it. We'd like to put it front and center, the way it is in mobile SDKs, making it easier to discover and easier to use. Okay, so we've talked about what virtual scrolling is and why we're interested in adding it to the web platform. But to really understand the nature of the performance problems we're trying to solve, it'll help to look at some examples.  So I actually recorded a bunch of real-world interactions for this talk, but I wasn't super happy with the quality of the recording, so I ended up creating dramatic re-enactments in DevTools with CPU throttling turned on. But what you'll see here is representative of the performance on the real device, and I'd be happy to show you on the device itself if you come find me after the talk. Okay, so first we'll look at how the size of the document impacts rendering and what that means for responding to user interactions and content updates. So I created a simple example to demonstrate. It's a bit contrived, but it exercises the browser engine in the same ways that real pages do. So this mocked-up content feed has just five items in it, and it performs pretty well. You'll see it has advanced features like a dark mode and a compact layout mode, and these are all made just using standard CSS techniques, changing classes. And then lastly, we have this slider here, which lets us increase or decrease the size of the items by changing the base font size in the document, which is a technique that many of you have probably used in the layouts of the items themselves are based on Ms, so that the whole thing scales. As you can see, this performed pretty well, but again, it's only five items. So let's see what happens if we bump up to 50 items in our feed. So I'm scrolling here to show there's more content, but don't focus on the scrolling performance. We'll talk about that in a minute. For now, we want to focus on the other interactions. And notice I added a jank indicator, so the screen flashes red when rendering gets slow. And we're not too bad here at 50 items still, although there are noticeable delays for the mode switches, and then you'll see there's some sluggishness as we start moving the slider. But where we really start feeling the pain is when we get up to 500 items or more. So the lagginess in this example is going to be impossible to miss. So you'll notice that when we go to dark mode or compact mode, there's a very noticeable lag and the slider is going to be virtually unusable. It's so slow to update. And if anything, it actually feels worse on the real phone than this. So again, this example is a bit contrived. You may not do exactly this on your page, but the effects it illustrates are very real. Rerendering the content on your page, any content on your page, whether it's in response to user interactions or changing data, it gets much slower as your document gets bigger. And on devices like this, it can kill your page. So let's jump ahead of it and see how much virtual scrolling might help. So this is exactly the same page with our work in progress virtual scroller swapped in for the scrolling region. And we've bumped all the way up to 5,000 items, but of course only a small fraction are actually in the document at any given time. And as you can see, we're pretty much back to the same performance we had in our original five-item list, and this is essentially how it feels on the phone as well. And remember, this is a very low-powered Android Go device. Next, let's see how virtualizing might help us at load time. So a quick caveat about this. Load time performance, how quickly we get something on screen, how quickly we make it interactive depends on a lot of factors, and virtual scrolling doesn't directly impact many of them. But to the extent that styling and layout are slowing things down at load time, virtual scrolling can definitely help. So being the big web nerds that we are, we'll use the single-page HTML text doc as an example. So this thing is massive, somewhere on the order of a million words, I'm told, and it's notoriously slow to load. So on my Android Go device, with a good but not great network connection because I'd gone over my data allowance for the month, it took about seven seconds to get something on screen. So for comparison, we've built a virtual scrolling version of this page out of duct tape and bailing wire. Basically, it loads the original doc into a hidden iframe, and then it populates the virtual scroller as the nodes stream into the iframe. And you wouldn't build a real thing this way, but it's an interesting test case, and it illustrates the impact. So as this visualization shows, we got something on screen much faster, just over three seconds instead of seven, and it actually gets even better from there. The original version on this Android Go phone was suffering from scroll jank for well over a minute whereas the virtual scrolling version is usable right away. As you scroll, there's occasionally a delay as it updates, but unlike on the original version, you're never sitting and waiting for seconds while the screen is locked up. So before we move on from performance, one quick word about scrolling performance because it seems a little weird not to talk about that when I talk about scrolling. So because scrolling is driven by the GPU, and it's a low-end Android Go device, you actually get pretty decent scrolling. It scrolls at a reliably high frame rate and it actually looks really good at normal scrolling speeds. But when you scroll quickly, something funny happens. The screen blanks out, goes completely white for long periods of time while the rendering pipeline catches up, and this actually gets worse as the size of the document increases, just like the other performance problems we've been looking at. So here, our virtual scroller, it turns out, significantly reduced the blanking problem. It happens much less frequently, and when it does happen, the renderer catches up much more quickly. The trade-off is that scrolling is mildly but noticeably less smooth overall. As you would expect, doing JavaScript layout on a CPU challenge device like this does impact the frame rate. But as you can see from the video, it's a very good experience, and it's a slow power device. Okay. So we know what virtual scrolling is. We know we want it to add it to the platform, and we've seen firsthand why we need it. We see the performance issues we're trying to overcome. So I want to talk for a moment about the process that we're going through. Because it's actually not that common in recent years for the web to add new high-level features. We had a bunch of things that we really want to do and treat this sort of as a guinea pig for how we might add higher-level features. We'll start with some basic principles. Anytime you're building something in the web platform itself, as opposed to in user space, it's important to get the very basic use cases right, because web APIs live forever. And it's much more important that we do the simple stuff right. So with that in mind, we wanted to make sure that we learned from prior art. There's obviously virtual scrollers on other platforms, and plenty of good work in the framework space. As I said, we want to make it simple. We want the feature to be easy to use. As much as possible, we want you to be able to create web content that you just happened to put in a virtual scroller as opposed to picking up a brand new API and thinking fundamentally differently about the way you build stuff. Make it work. It sounds trite than it is, but what I mean by this is everything needs to work. We talked about links. We talked about find and page. It's critical that accessibility works. We want tabbing from item to item to work.  After all, this is a performance problem we're trying to solve. The next thing we want to do is we want to embrace layering. We'll talk a little bit more about what we mean by that. Nicole actually mentioned this in the keynote. One of the important things we want to do out of this process is identify and implement any lower-level primitives that the browser may be missing in order to support this high-level use case. We also want to enable this thing to be used right out of the box, much like you use vanilla HTML and JavaScript. We don't want you to have to pick up a framework to do virtual scrolling. We'd like you to be able to use it on the web platform simply. But with that said, we also want to give frameworks and libraries a solid base to build on. And certainly the low-level primitives are things they can use, but ideally we'd like the virtual scroller itself to be something that they can take in whole or in part and layer features on top of for their own virtual scrolling solutions. And as I mentioned, this is all really with the idea of blazing a trail. We think that there's a lot of room to improve the developer experience and the user experience of the web platform by adding some high-level features in coming years. With that in mind, we want to use virtual scroller as sort of a lens or a testing ground for us to examine what it means to add new high-level features. And so we'll talk about some of these things as we look at the virtual scroller. So with those principles in mind, we sat down to do our homework. And the first thing we did was we set up what we called at that time the infinite list study group.  And each time someone would take the homework of looking at a particular virtual scrolling solution and reporting back and we would discuss it and we'd learn about what was working and what wasn't. And we documented all this here on GitHub. Once we'd done that for a while, we came up with a set of requirements and it was time to start building. Now, I don't know what this is. I think it's molding or something, but it looks like something I'd really like to build. So I put it on the slide. And we have the same sort of love for virtual scroller. So once we started implementation, we did that on GitHub as well. And one of the things you'll notice here is that virtual scroller is being implemented in JavaScript. And this obviously is sort of unusual for something that's under consideration for a web platform API. It's not typically how we build platform APIs. But this gets to the layering concept. We wanted to make sure that we didn't reserve any special powers in adding these features. And one of the best ways to do that is to develop things in the same environment that framework and app developers develop in. So the next important thing about the process is we wanted to be in constant dialogue. We talked about the fact that we're doing these things out in the open in GitHub, but we also have been talking to people all along. So we've been talking to other browser vendors about the ideas behind virtual scroller and the principles that we're trying to look at for adding new high-level features. We've also talked to framework and library authors. So along the way, we've talked to members of the Angular team who are working on the Angular Material scroller. We talked to the AMP team. We've talked to members of the Ionic team who are working on their own virtual scroller. And we've talked with Brian Vaughn, who's the author of React Virtualized and React Window as well. And we also have very active discussions going on in GitHub. So it's important to us that this process be carried out in the open and with the input of the community, including frameworks. Okay, without processes backdrop, let's go ahead and look at what we've built. So this is that example we were looking at before, and I show it here in DevTools just so you can see as we scroll, there are just a few items in the DOM at any given time. And when we scroll, you'll see them cycle in and out. And so even though we have a list of 5,000 items here, at any given time, we're only laying out styling, rendering a very small number of them. And as you can see, the virtual scroller itself is a custom element. And let's see how you would actually use that in vanilla style. So starting from a blank slate here, the first thing that we're going to do is we're going to use the browser's native module loader to import this. Now, this is also a new concept that we're trying out as part of the way we're thinking about higher-level APIs. Typically, browser APIs are sort of baked into every page. You may use them, you may not, but there's a memory impact and the size of the browser is impacted. We'd like to explore a pay-as-you-go model. And so we already have, in the form of the module loader, a way to dynamically load libraries and code at runtime. And so we're using that here. And you can see we have a proposed syntax for requesting something that would be part of a standard library provided by the browser. And I won't go into the details here, but you can read about it. So once we've imported it, we just put the virtual scroller tag in our HTML document. And this is what you get without doing anything more. You can see the virtual scroller has a default size, much like an image or an iframe. Not an image, but rather an iframe. And so it's not doing anything yet. Let's make it do something. So first, ordinary query selector to find the virtual scroller. We're just going to fetch some data. And then here's the first bit of virtual scroller API. It's an item source. You can assign this an ordinary array as we've done here. And then we'll call our async function. And we get that, which probably isn't exactly what we want either. So we wanted the virtual scroller to do something by default. And so what it does is it just takes the item and it tries to render it into the item. And in this case, it's string, and it doesn't look very good. So let's fix that. So the next bit of API is this update element hook. So here we're basically just going to take the contact name and put that in the text content. And there we have something that looks much more useful. So just a few lines of code, vanilla HTML and JavaScript, and we have a virtual scroller. So let's take a look at one more example. You notice the virtual scroller initially was empty. And by default, it will just create a div for each item. You can actually override that. In addition to the update element, there's a create element hook, and you can give it any kind of DOM you want. But you can also put a template inside the virtual scroller, and whatever is there will be what's instantiated for each item. So I'm going to go ahead and, in my update element function, I'm going to assign the image. And then lastly, I'm going to specify that I want a vertical grid layout. So out of the box that supports vertical and horizontal, I'm going to add a model normal and grid layouts. Layouts are actually pluggable under the hood. It's TBD, whether that gets exposed in the APIs that eventually ships. OK. So as I mentioned, we're taking a layered approach. We're not building fancy features like custom headers and things in. But it is important to us that these things work, because again, we want layering. So here's a case where we have headers interspersed with list items. These are all examples that you'll find in our GitHub repo. So the other thing is it's important that we want to support various loading patterns. So this is a common one where it's sort of an infinite scroll, and as you go, each item gets loaded, and you just keep scrolling. We also support the other common pattern where you scroll to the bottom, you explicitly ask for more. So again, we're validating that our basic constructs are working for these use cases. Fancy your features. If you've ever built stuff like this, worked with the UX team inevitably, they're going to want fancy stuff. So here's a proof of concept that shows that things like swipe to dismiss can work with this virtual scroller as well. OK. So we mentioned that we thought there would be some missing primitives that we might discover. And we think we found one. Specifically, it's called invisible DOM. If you remember our earlier examples, in this one, you'll see it's a lot like the virtual scroller, except instead of actually getting rid of and adding nodes, it's basically just making nodes invisible. Invisible DOM is in the document much like a display none element, but it's different from display none in that it can be linked to and it can be found by the browser's find in page. And so here's an example where we have a non-traditional virtual scroll type of content. This is a document, much like you might find in Wikipedia or a long-form news article. And you can see, here it is. We get a certain way down the list and all of a sudden there's nothing highlighting over in the window because some of these DOM nodes are invisible, they're just not there. And as we scroll, we'll see that they're basically being flipped to visible. And so when the virtual scroller is working with invisible DOM, this is how it works. So you'll see here we'll do some resizing, changing orientation, and you'll see that the layout is preserved. Again, this is just ordinary styling and layout on these items, and a virtual scroller works with them out of the box. This is what we were talking about when we said we wanted to make it simple. We don't want you to have to think hard about using a virtual scroller. So what we're looking at here, though, is the cool thing. It's links, and this is what invisible DOM is making possible for us. So when I click on one of those links, the DOM nodes that it's linking to are not even in the document yet. But, well, they're in the document, but they're not rendered. And so you get an event on them, and by default the browser will actually flip it visible and scroll to it. But in the case of virtual scroller, we're capturing that event. We are scrolling to it, but in the process of doing that, we're rendering all the context around it. So it's perfectly seamless. To the end user who's using invisible DOM with a virtual scroller, it's exactly as if the entire document had been rendered the whole time. And I am just about out of time, but I wanted to show you one of the exciting things about using invisible DOM with a virtual scroller is that it means you can actually put invisible content directly in a document. And we're talking with our friends over in Search, and the idea is that you'd be able to effectively have your content be entirely indexable, but to benefit from the performance wins of virtual scrolling by not having to render at all on first load. So very quickly, talk about the path forward. Again, very early days, but very encouraging results. What's next? More invisible DOM integration. We've really just started exploring how the two play together, because thanks to some great work from Rakina on our DOM team, we've just had working a version of it become available very recently. In fact, it's available behind a flag in Chrome Canary. We think there may be additional privatives as well. We've talked about some. I won't go into detail here, but invisible DOM is just the first. Framework collaborations. So from the start, we've actually in the repo had proof-of-concept integrations with LitHTML and with Preact, and for this talk, but I ended up getting cut. I did a basic React integration as well, but it's very early there, and we haven't worked closely with the frameworks on that specifically yet. More advanced use cases. So we saw some of those examples, but there are others that we have not gotten to yet. Performance optimization. It's pretty darn fast right now, but there actually hasn't been intensive optimization done on it yet. And then importantly, down the stack explorations. So one of the first questions we get when we talk about this is, why do you need a virtual scroller? Can't the browser just do this? And these are discussions that we're having not only externally, but also internally. And it's a long complicated story. Browser layout is complicated in much the way that AMP simplifies building pages. Virtual scroller can simplify layout by locking you into a much simpler model, and there are some wins there, but that being said, it's very possible that we can also pursue other types of optimizations further down the stack that get you some of the same types of benefits without even having to go to a virtual scroller, and those are certainly things that we're discussing. The standards process. So again, been talking to other browser vendors all along, but it's very early for this and other similar high-level features. And the list could go on. So if you're interested, I invite you to engage with us on GitHub. We have a very active set of discussions going on in the issues here. And here is the GitHub repo where you'll find us. And with that, I've been excited to show you virtual scroller. I hope you're as excited as I am to see it come into the web platform. It's time for another one. Yes, we're going to do another question, but also a few people have been asking about the Chromebook discount stuff. Yes, everyone here gets a 75% discount off one of these. Woo! The place to get that is the registration desk. It's free. We've been told that people are going to the forum space, but the forum space doesn't have that discount code. Please go to registration. I think they're quite good. You should buy one. Have you been paid to say this? Yeah, pretty much. Okay, let's do another round. Right. Now, this one is going to be about CSS properties and attributes. You're going to see a series of letters in a row. I think we call them words. You need to decide whether it's a CSS property or HTML attribute. You have three seconds to get each one, so you need to be fast. Right. Let's have a look at the ones that come on the screen. Here we go. Okay, default, touch action, Unicode. The cell padding there. That takes me back. Speak. Okay. Unicode base. Yeah, exactly. Zoom access key. I want you to have one of those. Oh, DC color. Remember that one? Yeah. Auto-capitalize. That sounds useless. I wonder what that's for. Gap. Sounds like a style thing. Gap. Who knows? I remember that one. Auto type DIR. Okay. The ground is closing. Let's have a look at which way you have all voted. When it appears on the screen at some point, I hope we don't need to get some around again because it's not ending. Right. Maybe I can do it manually. Here we go. Right. There we go. Excellent. What's the voting like? Default. We're saying that the Unicode is a HTML attribute. Okay. The answers. There we go. There's a small clue. CSS properties tend to have the hyphens in. Yes. That's not always true because we get a lot of SVG. So, let's have a look at the next set. I'm curious about this code base thing. Yeah. So, we're saying HTML attribute for the code base, HTML attribute for speak and access key. The answer, of course. So, what's code base? I don't know this. Code base is from the applet tag. Is it still a valid tag? Is it still a valid tag? Let's say probably maybe. Okay. That works. Everything in HTML. Speak is to do with how a screen reader or something would pronounce that bit. So, it's essentially sort of display, although not visual display. Access key, yeah. That's CSS as well. Let's have a look at the next set. Autocapitalized VG color resize gap. We're mostly thinking those are CSS properties. VG color is a HTML attribute. Yeah, that's from the olden days. Yeah. Autocapitalized is for an input element, and it auto capitalizes as you're typing. So, very much functionality. Yeah, resize and gap are CSS. So, let's have a look at the last block. Zoom, order, type DRR. Okay, everyone's saying Zoom is CSS. Yeah, and it absolutely is. I built my career on top of this CSS attribute. The Zoom. Yes, this is like when I was fresh out of university at the BBC, I built a career of knowing all of the IE6 bugs. And I would be called to different departments as like, we've got an IE6 bug. Let's get Jake in, and I'd walk in and it's like, I've got this, I just need to find the element to put Zoom one on, and then I'd walk away. Like, promotion, please. Amazing, amazing. Did they promote you? No. All right. Yeah, that's it. Okay, so yesterday, me and Jake came on stage to talk about the build app we built, which is a web worker, right? But we were honest about the little laugh edges of working with workers. However, Jason and Shuby coming on stage next had some ideas. Oh. So please welcome to the stage Jason and Shuby. Hi, everyone. My name is Shuby Panaker. I'm a software engineer working on the web platform in Chrome. And I'm Jason Miller. I'm a DevRel for Chrome. Our talk today is about a key strategy for the development of web apps and that is scheduling of JavaScript on the main thread, as well as approaches for moving script off the main thread. Jason and I have both been deep in this space exploring gaps and APIs for what we are calling achieving responsiveness guarantees. We're excited about the opportunity here, both with existing primitives, as well as the new APIs we will show in our talk. Right. Let's illustrate this problem of space using a demo. This is a simple application that searches through photos as you type. You can see here with this JavaScript control red spinner animation, it's doing a fair amount of blocking work on the main thread. While this is happening, the app can't respond to input, so typing gets cued. Looking closer, what we see if we pull out the profile or something like this, a sequence of long tasks that we are executing. We can see this on a simplified view here, so if we receive input and we start doing some processing in response to that input, say searching photos, rendering some list items, we're skipping frames already. But in addition to that, if we receive additional input while that task is running, it will get cued and only is able to execute once that has completed. So this is data captured from real users on real websites and it shows a breakdown of where Chrome was spending its time while handling input. So there's a lot of interesting data here, but we don't really have time to get into it. The main thing to look at is the amount of time we're spending in this v8.execute task. That is Chrome running JavaScript during touch handling and it's clearly the biggest contributor to touch input latency, both on average and also in the worst case. So a problem with our search as you type is there are a lot of different types of work happening here. And all of these different work have what we are calling grade deadlines. So for example, the user is typing in that search box, their input has to be responsive, there's ongoing animations on the page, they have to render consistently and smoothly. And then there's the heavy lifting of fetching search results, post-processing, preparing, rendering these search results in time . The difficulty is that it's hard for apps to balance these competing needs to reason about all these different deadlines and keeping everything meeting these timelines. Right, so we have a bunch of different types of work and each of those types of work has a different deadline. And what we need to be able to sort of work through this is priorities. So there's a couple high level approaches to try and achieve responsiveness . You can just be doing less work. And there are ways of doing this, such as in an infinite feed, you might only render what's visible. We just saw a strategy with the virtual scroller talk right now. Now, this is not always possible. Modern apps often just have a ton of work to do. So a second strategy here is chunking up work and prioritizing these chunks of work. In practice, though, this is very practical to achieve this manually on your own as an app developer. And we think there's a real opportunity here for frameworks to step in and help their users. Frameworks are in a great position to ensure chunking and prioritizing of work. So stepping back a bit, what we need here is some way to provide our chunks of work, our tasks, to a system that can hold them, say, in a task queue . This system can make good decisions about when to take tasks out of the task queue and execute them at an appropriate time based on everything that's going on. And this is the definition of a scheduler. So Google Maps is a really great example of an application that uses a scheduler to keep its interactions smooth. This app has to manage multiple different types of interactions and give a much higher priority to input response tasks. We can see that here. So let's say I'm panning the map and as I'm panning, additional tiles are coming into the viewport and need to be loaded. However, if I stop panning and I pull up the drawer at the bottom, all of a sudden that is far and away the most high priority task to execute. So those map tiles being loaded need to be deprioritized. So a key aspect of a good scheduler is to understand what is the best time. And this is an appropriate time based on everything that's going on, various factors like what's the type of the task, what's important to the user right now, what's the overall state of the application, what's the internal state of the browser, et cetera. So to understand this notion of best time, we have to kind of step down a level and look at the browser's rendering pipeline. The browser is periodically pumping up to 60 frames per second display rate and each frame has a set of things that happen in sequence. For instance, we have request animation frames followed by style, layout and paint. In Chrome input handlers are aligned right before request animation frame callbacks. So the point here is that there is limited time to do the urgent work that needs to happen in the current frame. And then the app has to immediately start thinking about preparing for that next frame. And the third type of work here is idle work which might be left over in the current frame or there might be plenty of idle time if no frames are being rendered. So this is the terminology we are using for these three types of work. We have user blocking tasks for the current frame. This is typically to provide the user an immediate acknowledgement of what they're doing. So in our example this might be keeping that typing interactive in the search box, keeping those animations going on the page, overall keeping the page responsive overall, buttons should be toggleable. Default work is this next category of work. This is typically user visible and this is preparing for the next frame or a future frame. And in our example, this would be the work of the post processing preparing the search results rendering them in time. And finally, the third category idle work. This is typically work that is not user visible. This can be at the end of the frame or if no frames are being rendered. Things like analytics, backups, syncs or indexing. So on the right here, we've sort of listed some existing primitives, existing ways how a developer might be able to submit work to the browser to target these priority levels. So for user viewing, input handler and request animation frames are great for this. It's also worth noting that micro tasks are suited for user blocking urgent work. They do not yield to the event loop. And we've seen some bad cases where developers are accidentally doing non-urgent or large amounts of work without realizing it's blocking rendering. The second thing, default, we have things like set time out zero, post message, these are really hacks that aren't a real primitive here. And we are working to fill this gap. And finally for idle, request idle callback is a great API. So JavaScript schedulers can be built today using these primitives. Now, while it's possible to build a scheduling system in JavaScript, they suffer from gaps, primarily because they don't have enough control on signals and, you know, to properly control scheduling. So we'll go through some examples. So for example, we've seen JavaScript schedulers are trying to estimate the frame deadline. So they're doing a whole bunch of bookkeeping, trying to guess at it, but they're doing it poorly because it's just not possible to do this well without knowing browser internals. So we're considering exposing an API for that. This input pending is a really useful signal for schedulers. And we are going to do that in a different way. So if you're doing an API, then there's other coordination work. So for example, handling fetch response priorities is pretty relevant. If you're doing urgent work for the current frame, you don't want your low-priority fetch responses to come in and interrupt that. In practice, though, there's a lot of other work that's happening in the browser. The browser might come in, or a post-message might come in from a worker. There's internal work, like GCN, and it's just not possible to codify priorities for all of this and expose signals. So this got us thinking, how about moving the scheduler one level down and integrating it directly with the browser's event loop, where we already have most of these signals and a lot of great information. And this would solve an additional problem. That is this coordination problem between multiple parties in the app. If you have third-party content or embedded libraries or legacy code or even other frameworks, they can all coexist and use the same scheduling system with consistent priorities. So this is a very early sketch of what an API might look like. The key thing here is a set of global task use targeting each priority level, and so it's really simple and straightforward compared to using immediate different APIs. The second thing is we think it would be useful to have a notion of user defined task use or virtual task use, and this would give developers more control over like managing a group of tasks and doing bulk operations, like updating priority, cancelling all the tasks, or flushing the task use if the app is going away. So here we can see sort of a simplified version of that map scheduler that we looked at using this task queue API. So first we hook into the user blocking and default task queues just to give ourselves a high and a low priority queue. And then we start listening for pointer moves events and each time we receive one of these events we enqueue a pan task with the coordinates of that pointer move. The pan task translates the map tiles obviously, and then it might let's say enqueue a low priority to detect any tiles that have moved into the view port and potentially load those tiles. The thing to note here is if we receive a new pointer move event before we've invoked this load more tiles task, that would be given a higher priority than loading more tiles, and that's exactly what we want. We give higher priority to input driven tasks. And let's say the team behind maps needed to track analytics or do something in response to pan gestures, that would be a good case for something like this. So here you can see most of the frames are in green and getting rendered in time. And this is what a well scheduled system looks like. The work is chunked up. There is high priority work happening at the beginning of every frame, followed by style layout paint in purple and green. It is immediately followed by default priority work in yellow to prepare for the next frame, as well as idle priority work being properly interleaved and this time is adequately utilized. Next. So all the API proposals we showed today are super early stage. We actually don't know what the end game here is going to be. This is a really great time to give us feedback and help us chart the course here. For web developers, we really think that there is an opportunity here with improved scheduling, even with just properly using existing primitives. For framework authors, we want to urge you to consider a scheduling system and collaborate with us now to develop the right set of APIs in this space. React's work on concurrent and time slicing has proven that frameworks can really play a good role in terms of helping apps improve responsiveness of apps. And we are already working with React and actively looking to form partnerships with other frameworks and apps. This is a link to our GitHub repo. Filing issues on the repo is a great way to get that feedback dialogue going. So what about work that can't be chunked, though? What if we have a bunch of JavaScript we need to execute and it's really difficult or even potentially impossible to break that work up? Here's an example that illustrates what I mean. Let's say we have a text editor that is bundling as you type. If I load in a decent amount of code here, things start to get a little bit slow. Every time the bundling process kicks in in response to my input, it blocks the main thread and this causes the cursor to freeze and it queues up my text input until bundling is completed. This really disrupts the typing experience. You can see that in the CPU profile here on the right. So it would be really difficult to break that work up into 50 things. So let's look at two reasons. First, I didn't write any of the bundler code, so modifying that would be a lot of work, particularly for me. Plus, there is a whole bunch of different libraries that are being used to actually make these things happen, those dependencies, and downloading parsing and evaluating those dependencies on the main thread blocks. So using background threads lets us offload that work. There's a few use cases that lend themselves extremely well to this approach. If you're building a computer-aided design tool, a game or doing encoding, these are great places to just start with threads. Same thing for AI, machine learning, crypto. If these are the types of things you're doing, you should start here. In the browser, our primitive for threading is the worker. So if you haven't used workers, you haven't used them in any way. You can send a message to the worker, and you can receive a message back. They have no DOM access whatsoever, and a very limited global scope, kind of just fetch and modules stuff. And they shipped around 10 years ago, and they're available essentially everywhere. So the API for workers looks like this. You will instantiate the worker constructor and pass it the name of a script, and then we can listen for messages coming back from the server. So we're sending in a message that's an object, and this describes that we would like to invoke a compute hash function, and we're going to pass it the contents of a file expressed here as an array buffer. This second argument to post message is interesting. This tells the browser to, rather than structured cloning the array buffer, it will transfer it in. Finally, once compute hash has completed, it's ready to go. So under the covers, this post message of the data is incurring a serialization on the main thread and it's getting queued up, hopping over to a worker thread, followed by deserialization, and end to end, this is called a thread hop. And this thread hop has a cost, and primarily from the data being subject to what is called structured cloning, which is a copying behavior while recursing the JavaScript object, the size of the thread hop. So one downside of the post message API is that it doesn't have a notion of statefulness between the request and the response.  Right. So we've seen how to communicate with a worker using post message. There's actually a number of ways you can do this. A second way would be to use post message API and you get back two ports. You can pass your other port to some other context like a tab or a frame or a worker, and you can message between the two. They have the same interface as we just saw. Another one would be broadcast channel. This is sort of like a message channel that's shared to all contexts associated with an origin, so all tabs, frames, workers, service worker, and all you do is you instantiate a broadcast channel with a channel and you have a fourth way to communicate. And this is transferable streams. It lends itself really well to things like audio and video where the format you would want to use to express these things is streaming. The thing with all of these APIs is that they're message based. And based on some of the common usage patterns that we've seen and what we've heard from developers, we think there might be a case here for a higher level API. So we've seen solutions to this in user land through libraries .org. These all help coordinate messaging across boundaries by abstracting that post-message using something called proxying. So messaging certainly improves over a post-message, I'm sorry, proxying improves over post-message, but it comes with a number of downsides. Every method called to a proxied object incurs this cost of a thread hop and this can come as a surprise to developers. Platform gaps in these APIs, these APIs don't really have a notion of a backing thread pool or a concept of managing threads and resizing the pool. And better libraries are not able to share the same thread or thread pool. And for complex APIs, it can be impractical to recreate this API surface cross thread. So this raises the question is there an opportunity here for better integration with the browser? Is there an opportunity to provide a more compelling API? So this, we think there might be a use case here for something that looks something like this. So here we're passing the name of a function in some other context and some arguments to a theoretical post-task method. This post-task method would return a promise that eventually resolves to the return value of that function somewhere else. This abstract code helps us move from a model to a more task-oriented model. So in looking at the requirements for a better API, we considered other platforms. We looked at iOS and Android, which have plenty of precedent for usage of background threads. In particular, iOS has an API called Grand Central Dispatch, which is a very stable, well-proven API that's loved by iOS developers. Android, amongst other things, has something called Async Task, which is a very stable API. We talked to framework developers and experts in usage of these APIs who were deeply familiar with the pitfalls. And we learned things. Some key things we learned in terms of the basic requirements we want for our model is, number one, good ergonomics, a way for developers to off-load work by just thinking in terms of submitting tasks versus coordinating over threads. That's shareable with embedded libraries and other parties in the app. And finally, system-controlled thread management, where the system can be in control of making decisions on resizing the thread pool or decisions on where to run which tasks. So we set off on a path towards building a basic task-Q-based API inspired by Grand Central Dispatch. And a naive API might look like this. Let's say we have three tasks, A, B, and let's say each one depends on the results of the previous task. And we can submit these tasks from the main thread over to worker threads, and then we'll start getting responses back. So here for three tasks, we paid the cost of six thread hops. There's a few downsides here in gotchas. So for one, these thread hops can be expensive on lower-end devices. And depending on the data size, it can be up to 15 milliseconds. And this can add up. This means that if these hops are in the path of user interaction, this can add up to multiple frames worth of latency now. On Android, we've actually seen this in practice in the real world in their usage of async tasks. So one conclusion here is this notion of default posting back results to the main thread is not a good idea. Besides the latency issue, it can cause congestion in the main thread. So we're going to take a look at some of our Q build-ups. And then you might remember from our earlier main thread scheduling talk, we're doing all this work to carefully chunk up our work and, you know, execute our high priority and our default priority work. And all these post messages coming in at random times, messes with main thread scheduling. A second thing to note here is that we're going to have some of our Q build-ups in the main thread. So this brings us to a new proposal we have that incorporates some of our learnings from other platforms. It lets developers avoid sending data back to the main thread. It lets you chain tasks together without data transfer and pay the return cost only once. It also minimizes thread hops using a built-in file. So let's dive into that. If we revisit the code editor that we showed earlier, the one that bundles JavaScript as you type, if we do this using task worklet, we can leverage some of these features to improve performance fairly considerably. Because task worklet avoids transferring data between threads, the bundling and minifying tasks in this demo can actually all reuse the same AST that is generated from the minified code, which is a relatively small string, actually gets sent back to the main thread. So the implementation looks something like this. First we create a worklet module, and that registers named task processors. It just classes with a process method. Then over on the main thread, we can coordinate that data flow using this post task. So we're going to parse the code and then pass that resulting AST through the main thread. So what we do is that none of these variables are actually holding values. These are just pointers to data that exists in the thread pool. Data transfer back to the main thread only happens when we await the result property of that last task. So doing this in a typical worker's implementation would normally take six hops as we saw. We executed three tasks. We need to pass a message down and back up for each of them. In this case, we can transfer data between tasks. Task worklet is also backed by a thread pool. So let's say we start off with a task that produces a large set of images. When we post a task with some of those images as its argument, it will attempt to run in the thread where that data is already available. So data is never transferred between threads in this case, and that leads to fewer thread hops. To take advantage of pooling though, if there is no resource to transfer data between threads in order to get parallelization. And then finally, let's say the result that we're looking for here is actually just a comparison of the number of cats versus the number of dog photos since that's what's important in the end. In this case, the only thing we ever transfer back to the main thread is a single integer. And as you can imagine, that's extremely cheap. So we've been thinking a lot about what the future of web development is. We have libraries like comlink that use reflection to emulate the interface of some code running in a worker so that it can be called from the main thread seamlessly. In the future, we think we might move towards a task workload model where developers approach multi-threaded web programming in sort of a different way. You have a thread pool that's managed automatically, named tasks, and this concept of a task graph that optimizes execution and data flow. So we're looking at a lot of things that we're looking at in this early proposal. We are looking for feedback and we are looking for real-world use cases. There's an implementation available in Chromium behind the experimental web platform features flag. And also we have a polyfill and some source code and demos available at this GitHub repo. There will be a link at the end of the presentation as well. So there's been a lot of interest in this project. We've done a lot of work and apps. So we dug into this in the last few months to understand how far can we get with just using the worker API as a way to achieve threadedness. And to set some context here, a new worker doesn't just spin up a raw OS thread. It actually creates its own JavaScript environment on top of this. And part of that is what's called a V8 isolate, which has a V8 of the OS thread. A key implication here is that the worker, by creating its own JavaScript environment, is not able to share data or code with the main thread. And this is fundamentally different from background threads on other platforms and other languages. So this has implications in terms of using workers in a mainstream way. And by that I mean when the worker is in the path of user interaction. So here we looked at two app development models using worker. The first one is doing state management in a worker. And this is where you can do sort of the heavy lifting business logic stuff in a worker. And the second model is goes even further and does the bulk of rendering in the worker. Now while worker doesn't have access to the DOM, there are libraries like worker DOM so you can do virtual DOM updates in the way that you want to do. So this is where you can do a lot of work in the environment. So real apps have been built using these models. However, there are some significant challenges that we want to sort of highlight here if you're planning to go down this route. The first thing is that it's hard to have synchronous access from to a worker. But real apps need synchronous access. So you can update that app state on a worker. And this means you now have to maintain and replicate this app state in both places and synchronize it continuously. And this has a cost in terms of thread hops. The second thing here is that the worker has to be bootstrapped with all the script and modules that it needs. Because like we said it cannot share code with the server. So we run benchmarks and to kind of dig into this base cost of a worker. And these are some numbers from a medium Android device. Startup takes upwards of 10 millisecond. This is again a Chrome on Android. A thread hop varies anywhere from 1 to 15 milliseconds depending on the device and the size and type of the data. Look out for a block post that will be identical to and we will have some detailed links to our benchmarks and data there. We also set up more realistic benchmarks. These were, we built apps that were representing the app development models. We mentioned that is the state management in a worker and rendering in a worker. And we did a ton of runs on real mobile devices both with and without worker. And we looked at a variety of metrics. We looked at a variety of metrics. We looked at memory metrics to rendering metrics such as frame rate and input latency. And we approximated input latency using cycle time. So again, the block post will have more details on this. But I do want to highlight one bit of interesting data. So this is basically showing runs with an app that is running without worker. So what we are seeing here is that on worker, we are seeing a higher, more improved frame rate. But on the flip side, we are also seeing a higher input latency. So there's a fundamental tradeoff here between improved smoothness versus user latency. Workers are able to sort of free up the main thread by offloading work. And so they are able to free up the main thread to focus on rendering. And fewer, less script means fewer long task hiccups on the main thread. Again, on the flip side, input latency suffers from thread hops. And the worker environment is a limited environment and doesn't have APIs. And it's not just the DOM. There are many other APIs that are still not available, like media, audio, software. But they might do it at the expense of a bit of input delay. There's cases, though, where this is completely worth it. So AMP script is a great example. AMP script renders using workers in order to sandbox potentially misbehaving JavaScript. Slower or problematic code that's running in the worker in this emulated DOM can't negatively impact the AMP document. And so for AMP, the benefits they get out of this is that they don't have a lot of latency that they get from transferring events. So we wanted to summarize when to use workers, but it turns out there's no perfect rubric for this. So there's a couple of hints you can use, though. If you have code that blocks for a long time, if you have code with small inputs and outputs, or something that follows the simple request response model, you might be in a position to start off with a response or just code that needs minimal overhead. You might want to start off with a different solution. You could approach workers later. When adopting a threated approach to state management, make sure that your state management and business logic outweighs the cost of creating a worker and sending and receiving messages. Make sure that your worker is pulling its own weight. So we're at the beginning of a fairly major shift in how we're doing this. We're excited to explore new possibilities for effective scheduling and threatening, and we hope that all of you are too. So we just want to leave you with some of these key messages from our talk today. It's hard to achieve responsiveness guarantees because there's so much work happening in modern apps, and we think scheduling is a compelling strategy for tackling this. There's an opportunity here for people who are in a good position to play a big role here. In terms of offloading work from the main thread, you can think of using worker as an extension to better main thread scheduling. Some types of work are better suited to worker than others, and we think new APIs like task worklet are going to be compelling to utilize worker for scheduling. So that's about it. We'll have a blog post coming up next week. Thank you. Thank you. Thank you. Thank you. Again, the links to the GitHub repos. Issues on the repos are very welcome and appreciated and a great way for the feedback loop. And do not hesitate to reach out to us on e-mail or Twitter. Thank you. The usual pattern? Shall we do a quiz-y question? I don't know if you've heard of JavaScript before, right? It's this programming language thing, whatever, scripting there. But there's a group that do all of the proposals and stuff. Yes, so TC39 is a technical committee 39 at ECMA international, which is an international standardized organization. Anyway, so TC39 is a group that defines a future JavaScript features, and the way it works is people submit a proposal and we discuss it. So we're going to see a name of a proposal and you need to say if it's a real proposal or not, a fake proposal. Just something we made up, right? Okay, you're going to get a few seconds per item that comes up. So guess quickly. Here they come. Right. Okay, what have we got here? Object seal, that sounds good. Power ranges, that's probably definitely real. Logical hash pipe, that sounds delicious. I'm curious to see how to use it in my code. Tiny Indian. Logical assignment. Exceptional seal, brilliant. Rolls and realms. I think I've seen that movie before. Knowledge correlation. Temporal permanence, that sounds like optimum prime spreadable mixings. These are just all words. No idea. Imagine going to TC39 meeting. It's all words. We'll be saying everything in words. Optional training. I don't know. Membrane, smooth operator. That sounds great. The question has closed. Okay. People are very confident about object seal. Object seal, that sounds great. Power ranges, logical hash pipe. We're not convinced about power ranges. Okay, fair enough. Wasn't sure about the logical hash pipe there. That sounds good. Let's see the answers. They're fake. Object seal is real. Blind ref is something you would complain about in soccer. Just to make sure, these are the proposal. I'm not promising this is going to make it to JavaScript. Let's have a look at the next group. What have we got here? Tiny Indian. Logical assignment. Let's have a look. Let's have a look at the next group. I don't want to have an exception. Frozen realms is a real thing. Yes. A realm is a global, essentially. If you create an iframe, you've created another realm. It's a frozen one of them. Brilliant. Excellent stuff. I like the way you just went, yeah, Jake doesn't know what he's talking about. Brilliant. I'm being careful. I don't want to start Twitter fight somewhere. It's a good poll. I have ideas to bring it to. People think something about spreadable mix-ins. I shouldn't make a proposal about it. People want it to be real. If that changes the winner, we're not going to change prizes. Okay, fair enough. Optimum primes is of course a robot. Next one, optional training. Men blend. People kind of spread. It's fake. I like that. 55% of people thought smooth operators won. So, yeah. Great. Is that it? Yeah, that's it. Who's speaking next? Well, up next, talk about application architecture stuff. A couple of people who've been on and off the stage over the past couple of days. It is Paul and Surma. Big round of applause. I was on the way to the office this morning and I realised it is very much like web debt. Rush hour. All the traffic. Everybody is trying to get to the office at 9am. All these people in their cars and on trains, everyone is just rushing and nobody can move for anybody else. And I think that's like web because you've got... Please explain this a bit more. You've got the main thread. You've got this one thread and on that main thread you've got all this work. Everything is running and everybody is competing for this one resource, the road or in this case the main thread. Oh, so like Mr Framework has a car Mr Paint has a car Mr Business Logic has a car and they all just want to go on the road but it's already full. Exactly. And everybody is in the same boat where everybody gets the angry tweets and sees kind of all this performance advice and nobody knows what to do because all this stuff is just strained into this one place. Yeah. Look at that production value. I know, right? Now. Anyway, look, rush hour. As we described in that video, that's kind of how we feel when we look at the web at large we look at it and we go all this code should be here but it just feels like the traffic is the problem. There's just too much going through the main thread. And traditionally the main thread is full. It's overworked and underpaid. You would say, cool, I'd use threads on any other platform. I'd do that. Just spin up a thread, put some code there, run it there, call a function. Hooray, everyone's happy. But turns out JavaScript and the web is special and it is inherently single threaded so you can't do that. Right, exactly. Every thread is kind of its own little universe, isn't it? We heard it's a V8 isolate, right? And so you can't just go just call this on another thread but you've got some shared stuff that you can work on. So that's a challenge. And then it gets more interesting because we're trying to build, I don't know, like a chess game, just for argument's sake. And you've got a chess engine and the chess engine is, it takes a few hundred milliseconds to calculate a move. Or more, I mean it gets exponentially difficult.  And you're like, I was already behind on my perf budget. If you could just not do the 60 frames a second thing, that would be great. And then some even brighter spark comes out of VR. Yeah, I want to stand on the chess board. Yeah, I want to be like right in the game and you're thinking there was already rush hour. Turns out frame rate quite important when it comes to VR. Yeah, and it could be voice. There's so many things that it could be. So this comes increasingly unlikely for you to be able to do this successfully on the web currently. Right. And so this is the question that we have been thinking through for the last little while. What do you suggest think of to help? We have two birds, we're looking for stone. Exactly. And... Oh, that went well. Okay. Wow, I really need to think of what I was going to say next. Okay, this, yeah. Acto model, yes. So we kind of stumbled over this. The actor model is, as it says right here, about 45 years old. There is languages that use the actor model to this day and successfully so. And we kind of realized that it's actually a really good fit for the web. Yeah, because what it does is it kind of, it makes a feature of that single threadedness of JavaScript. But we like to explain, if you've come across it before, great. If you've not come across the actor model, we like to explain it in a very specific way. So check this one out. So when we did supercharge, you saw us on screen. But behind the cameras, we had an entire crew. And that means we had one person working the camera, we had one person worrying about that our audio was good, we had a director, and each of these people was so responsible for that specific device. And instead of going over and pressing one person's buttons or just messing with settings, those people actually have to communicate with one another to get the job done. If you like their actors in the system, but they've got to send messages to one another and communicate and collaborate in order to get the final thing working. So that's kind of where more video, more production value. That's good, right? So that's where we kind of see a mentality that fits the web really well. And you start thinking about where can you draw a line for individual pieces of responsibility in your app. And instead of thinking about classes and how you call the method on the other class, you can now think about these actors and how you can send the right message to request something to happen. Think about how, at a conceptual level, like how would you think this through? What would it look like a little bit? Okay, so imagine you have an actor, and its job is to run your user interface. That's its area of ownership, that's what it does. That's its job, and only that. You might also have another actor whose job it is to handle state fear application. And yet another one who handles the storage. Now, imagine in your app that the user interface will actually be something like favoriting an item. The user interface, when the user taps on it, will send a message over to the state that says this was favorited. In turn, the actor handling the state will send a message to the storage to say we need to remember that they favorited this item. Now, we could also, at this point, introduce a new actor into this story. Something that could broadcast. Because when the state changes, typically what we'd want to do is to run the storage to be reflected in both, I suppose, really. Yes. And so you can kind of see here that that really is a separation of concerns. Ah, the click. There we go. Anvil transition. Do recommend. It really helps you to think about your app in a different way, helping you to figure out where does new code