u go. It's clear how I just feel, I get to feel really smart at things I looked up in advance, you know. But I mean, isn't that how we know everything? Yeah. You know, I shouldn't feel too bad about it. It's only a search query away. You didn't know until someone told you what you looked it up. So, there we are. So, I guess we should get on with the next talk. Our next speaker is going to be talking about storage. It's Drew Knox, everybody. Drew Knox. Hi, everybody. So, as they said, my name is Drew Knox. I'm a PM on the storage team. Work on a few other projects, but storage is really what I'm here to talk about today.  So, please laugh at all of my jokes. Otherwise, we'll be cripplingly embarrassing just throughout. So, again, please thank you for that. So, before I get started, I want to do a show of hands. I'm the talk right after lunch. So, you guys are all probably in food comas, not really paying attention, catching up on email. So, a little calisthenics to get you guys going. First, how many of you are still capable of raising your hands? You didn't eat too much. You can, yeah. All right, good. A few people lost, but that's okay. All right. Now, on to the real question. How many of you have used client-side storage in a meaningful way, not just playing around with service worker in a demo app in one of your sites? All right, now, keep your hand up if you viewed that primarily as a critical performance optimization, not offline, it's about right. So, when we look at these kind of numbers through Chrome usage metrics, we see that about 2.5% of page traffic uses things like index DB or cache storage. So, my goal today is to convince all of you. So, hopefully you'll all have your hands up next time around at CDS, that client storage is the most important performance optimization you can make for load time in all browsers. And most importantly, because we all know that caching and all this is important, I wanna convince you that it's available today and that it's kind of low hanging fruit for you to pick up everywhere for all of your users. So, why is this important? We've heard this number repeated a lot, which is that you lose half of your users if your site takes more than three seconds to load. I won't belabor the point, but it's pretty scary, right? It's kind of a horror movie. But when you think about it, it's actually a lot worse than that because on the average 2G network, it takes three seconds just to get the first byte. So, we're kind of already hosed, right? We're fighting an uphill battle and what's worse, 320 milliseconds is how long it takes to load one megabyte off the network. This is really hard. The deck is kind of stacked against us. So, we need some tools to help us not just improve our loading performance, but avoid the need to hit the network at all. All right, so, we know it's important. We know we've gotta do something, but I don't just wanna preach a horror movie. I wanna give you guys some actionable steps. So, in my talk today, I wanna walk through how you should reason about spending your time on client storage, where the biggest wins, the least amount of work for 80% of the value, some technologies that you can use along with some libraries that'll make it easier, more ergonomic, how much storage space you have available, and then if you guys are all really good and you laugh at all my jokes and my grandma's really proud of me at the end, I'll give you guys a view of some of the future things we're looking at that are kind of exciting. Now, before I move on, I was told I should explain the first line because nobody thought that how you spend your time that these emojis were conveying that. My girlfriend said it made no sense, but she's also an iOS developer, so what does she know? How are you going to invest your time? Web developers are pulled a thousand different directions. Lots of us are full-stack engineers. Unfortunately, we're working in a place where Flexbox is still one of our most powerful layout primitives. We don't really have infinite resources to do infinite things. So, before I get started, I want you, for the purposes of this talk, to think about storage as cash, not offline support. Offline support is really important and it's something that's been touched on a lot. I just want to focus on cash as a performance optimization here today. All right. As a cash, you kind of have this spectrum of investment that you can make. Browser cash, all the way on the left, is sort of the default. It's relying on the browser to get things right for you, hoping that your responses are cashed and that they aren't cleared before the next time the user visits. And on the other end, you're building a spaceship. This is service worker, cash storage. You're optimizing everything to the nines.  This is sort of what you've been hearing from a lot of folks. So looking at the first one, browser cash, doing nothing, it does have some real benefits. You speed up, repeat visits for your users and that's not insignificant. But unfortunately, it only works for network responses. It's unpredictable. You don't know when it's gonna be cleared out. And it's got pretty coarse granularity. It's the level at which you served up files. So this is not great. It's kind of sad. Optimize browser cash is probably what a lot of you are doing today and it's a really good step. This allows you to not only get repeat visits sped up, but you can actually get some proactive page load improvements using things like link rel equals import or any number of things to try and load things before they come in. But it still only works for network responses. So these are a lot of the optimizations you see people, you've seen people suggesting sort of off-handed as they've been giving talks. It's still unpredictable because again, you're relying on where the browser is storing things. And there's not much granularity here either because it's still on the level of network resources that you've served up. Still not great. Content caching is where the first big step function can come in in terms of improving performance. You get proactive page load improvements like before. But now you can work for all response types. So this is when I say content caching, I mean things like saving image blobs in cash storage if it's available or in index DB and then serving your image tags with a blob URL, all kinds of things like that. You have some predictability, right? Because the things that you're storing in cash storage or in index DB, you have control over. But you're still using network responses for some other things, so it only gets a yellow here. It's not perfect. You have content granularity and this is really important. Granularity is something where you want to be able to change something and not have to redownload your whole bundle. So the more you can break things up and have your cash invalidate for only small pieces, the better. So again, you get granularity for content but not for your network requests. So it only gets a yellow. This is still pretty valuable though. It gets a smiley face from me. Full cash control, the spaceship. This is a lot of work. I'm gonna be honest with you guys. I've never effectively done it and I work on this team and I should theoretically be able to say I've done a thousand of these. So it's great when you can nail it and you've seen a lot of really big production apps that have but with this comes a lot of work. You get proactive page load improvements like before. You get all response types again, that's great. It's fully predictable because now you're pulling in even the network responses into a cache that you control and that's really valuable. You can guarantee your user a certain performance level. You also have content granularity for your network requests and your content that you're serving. And as a major bonus, you get offline support which people have talked about a lot. So I would be crying tears of joy if everyone started building their apps like this today but I understand that that's pretty hard. Realistically, I think you guys are gonna wanna sit somewhere between the optimized browser cache that most people are doing today and content caching. This is kind of the sweet spot, right? If you can serve all of your content from index DB or cache storage or something like that now, you really have access to storing all of your content even if you're not building that spaceship with ServiceWorker. So you can get full performance levels for your site, not just the app shell or something like that. I've talked a lot about how this is maybe not too hard. It's kind of low hanging fruit. It's really important. But let me put my money where my mouth is and dig into some code. So first of all, as I put this together, I really fretted about whether or not I should put my thens on a new line or attached. I was afraid I would get flamed one way or the other. I went with their own line, but please don't hurt me. That's my best go. So here I'm using a Redux app. It could work with any framework, right? You could use your own view binding library. I just create my store, get it set up. Here's the magic part. I'm using an index DB wrapper library to store my state essentially whenever there's a change. This is done asynchronously, so it's not going to block the main thread. And then later, when I'm re-inflating my state, instead of hitting the network or pulling from Firebase or something like that, I grab it and fire a database-loaded event, which will reinstate my state without having to hit the network. So this kind of pattern, as you can see, was only three to five lines of code, and it can avoid an entire network hop for your whole app, right? You have your entire app state all saved local disk really, really easily. So this is a pattern that I think works really well with Redux-style apps, but it really can work for anything. It maybe has a little more work if you don't have a single object you're trying to save. If you wanted to tweet this, here's a good slide with all the syntax highlighting. In general, there are a few best practices. I hinted at them, but just to make them clear, when you're managing your cache on the user's device, you want to make sure you're doing client-side chunking. This means you might pull in an initial bundle and then kick off requests for smaller, more granular pieces so that you can revalidate only small chunks as things change. This pattern is a little more complex but can really save your network bandwidth. You also want to preload pages the user might be about to visit. So if you imagine you're on some news site, you might want to load all of the articles that are shown above the fold or something like that. You also want to save commonly repeated components. So if you have a hero image, a logo, anything like that, just save as many of them as you can. Get rid of as many network hops as you can. What should you be using to do this though? You guys might be aware that the web is not really one for having a single answer to a problem. There's lots of different ways to do things, but thankfully it's pretty simple in terms of what you want to use on the browser. So if your data is URL addressable, you should use the cache storage where it's available. It's really simple. It's kind of just like a key value pair. Works really great with service worker. So it's your no-nonsense easy, easy solution. If you've got structured data or if you have a lot of users who don't have access to cache storage, IndexDB is where you want to go. These two combine. They're asynchronous. They're modern. They're getting lots of attention from browser makers. This is sort of your bread and butter. This is where you want to be doing all your work. Now in terms of availability of cache storage, I have here, can I use usage weighted slides? It's available in a lot of places already. So I know some of you are thinking, oh, I don't want to deal with having to do progressive enhancement or fall back to IndexDB, but you can hit a lot of your users with cache storage today and it's only going to improve in the future. So I have here just a few libraries that we think on the Chrome team are great for helping to improve your interactions with IndexDB. They all give promise support. Some of them give database sync. Some of them even try to recreate SQL syntax, but these are all great libraries in terms of ergonomics, but also they've thought a lot about making themselves minified so that they don't impact loading performance. So that is a really big win. For cache storage, it's a newer API. There's not quite as much available. We heard from Jeff about ServiceWorker Toolbox, ServiceWorker Precache. Webpack has the offline plug-in, but otherwise there aren't quite as many things that are available now for use. All right. If I had to guess, I would say this was probably the area you guys were most skeptical when I started the talk. You are making websites, right? We aren't using device resources. This is the whole point of the web. It's ephemeral. It doesn't stick things around. I'm sure that's been changing as we've been talking about ServiceWorkers and kind of convincing you guys of offline, but it's still a real question. How much space do you get and how reliable is it? So at first I started looking at empirical ways that I could do this, right? Small demo apps to try to fill the cache, fill the storage partition and see what would happen, but then I realized why don't I just email all the different storage teams and the different browsers and ask them how much space is available? And it turns out that worked way faster. So the browser quota limits today are, they kind of fall into two camps. So we have percentage base. Chrome gives you 6% of free disk space per origin.  It's 10% shared across ETLD plus one. So this is like play.google.com and movies.google.com would share storage. Safari gives you at least 10% of free disk space. And Edge is, well it's a little bit more complicated, but thankfully it's still fairly reasonable, right? Like Edge is largely a desktop browser. It's got, so you can rely on being in one of the higher tiers. So you don't have to worry about all four of these all the time. And based on usage statistics and sort of looking into our own telemetry, we found that a simple number, simple rule of thumb is that you have 50 megabytes available on all devices and all browsers today. So this will get higher as you're working on higher end phones, but you can think of this as your minimum budget that you can use to try and improve performance on your site. If you remember my slide before, or a ways back, if it takes 320 milliseconds to load a megabyte across the wire and you've got 50 megabytes available to you, that's 16 seconds of load time that you can save averaged across all your users' visits. That's pretty huge, right? 16 seconds could take that 19 second loading app down to three if you were able to condense all of those network hops into something that you could cache. If I could I would take this off and I would do a mic drop because I think that's probably one of the most exciting things to me about client side storage. All right, but with great power comes great responsibility, right? We're now using resources on the user's device and this is kind of reinventing what we think is the contract we make with users. So first and foremost, you need to make sure you're measuring and thinking about your app's overall storage footprint. So this is something like figuring out your eviction strategy to make sure you don't just balloon up to 6% after three visits. But the whole point was we wanted to be using the user's device. So we can't just keep arbitrarily lowering our storage footprint, right? That would get us back to where we are today. So the second number that comes in is your read to write ratio. And this is something that Chrome Storage Team thinks about globally as well. Which is where we try to make changes to our eviction policies that reduce the storage footprint without lowering this ratio. That means we're trying to clear out data that's never gonna be read again. Now sometimes you'll clear something and maybe it was gonna be read in three months, right?  So another metric that you can look at is when you store something, check to see if you had cached the resource before. And if you had, look at the time difference between the two and that'll give you a sense of how long of a horizon was this sitting there for kind of useless on the user's device. So these are the three numbers that Chrome looks at and Chrome really cares about. And I think it's a really useful way to think about storage, but I would love to hear from other people if they have other metrics that they think are important to track. It's a really interesting space. All right. Your eviction strategy is not the only thing at play though. The other browsers have eviction strategies of their own or at least some of them do. So for Chrome and Firefox, we evict your storage or any storage on the device. When Chrome or the disk is full, we evict the most least recently used, most least recently used, that's not great. The least recently used domain from the list. Now it's important to note, this is very rare. Chrome clears a domain storage less than 0.1% of the time. So for the most part, when you store something it sticks around, but it is something to keep in mind. Safari and Edge however, don't clear index DB. So you can treat that as persistent. Now on Mozilla or on Firefox and on Chrome, there is something to try and help you work around the eviction policies when it's important. It's called persistent storage. It shipped in Chrome 55 and it's in development with Firefox. So the way this works is you essentially request the persistent storage permission and then Chrome will exempt you from automatic clearing. Well also, when the user clears browsing data, pop up a prompt for any persistent storage sites that says you're also gonna clear these, is that okay? So this is trying to help make sure that if you've entered a contract with your user that something should be available offline, you can guarantee that. Now unfortunately, when you do user surveys and you ask them about storage, it becomes pretty clear that it's not something they either want or are able to effectively reason about upfront. If you ask a user, hey I'd like to store 100 megabytes of your data, is that okay? They'll either freak out and say no or they just won't really understand the question. But they are very good at reasoning about your storage is full, which site would you like to clear? So because of this, we try to avoid showing a permission prompt when you request durable storage or persistent storage. Instead, we have a heuristic, which we use to either automatically grant or deny. And the heuristic is essentially, if you're treated like an app, you'll get app like storage persistence. And that means if you've been added to home screen, if you have push notifications, if you've been bookmarked, or if we've seen if Chrome has tracked that the user has engaged with your site a lot. So if any of those hold, you'll get the permission, otherwise it'll be denied. We recommend that you hold off on showing offline UI until you've received that permission so that you know it'll be around. Certainly not a requirement, but it's a little bit of a best practice. And then use the quota estimate API to make sure that you aren't ballooning your storage or you want to make sure if you have a regression where you get some kind of storage leak, you can clear it up because now you can't rely on the browser to protect you anymore. You have to kind of take your life into your own hands. All right, that's sort of the end of my practical area of the talk. You guys laughed at a few of my jokes, so I like you. I feel like we've grown close over this time. I want to give you a look into what we're thinking for the future because I think it's important. I think it's going to change the way we think about storage and apps and offline and all of these things. So first and most importantly, we want to give you guys more space. We're kind of channeling our inner Elon Musk and get more people with more space all the time. This is kind of a new paradigm. On Chrome, we're thinking about how can we start giving PWAs or web apps in general access to as much device storage as native apps get. And we want to do this because we think as PWAs become more common, the divide between apps and PWAs and all these things are going to become less clear. And so we want to give developers all the tools that they need to make great experiences. Some of you might be cringing or freaking out. It is a little bit of a divide. You could go to a website and it could take all of your storage. So this is something we're thinking about very carefully. And again, those three metrics I talked about before, we're tracking those very closely and we're going to be ratcheting this up slowly to make sure that bad ecosystem changes aren't coming into play. So this is something though to be looking for storage increasing over time. We're also thinking about some new functionality and it kind of falls into two stages, right? We have one set of things that are in development. They're actually pretty far along.  So if you have a kind of UI that uses something like that, it's really effective for making it quite simple. Async cookies are going to be a big win. They'll also be available in service worker. So that's pretty awesome. Both of these are Wikig or YCG specs that have some degree of implementation. So they're coming soon or sooner rather than later. Then we've a couple areas of exploration that we're looking at. So I mentioned a lot of libraries that will give you promise support for IndexedDB. We know it's great. We know it's the way that people wanna work with async code moving forward or at least a large subset of people wanna work with it that way. But it turns out layering on IndexedDB promises to transactions is kind of thorny. It turns out to hit all the edge cases, it's hard. So this is an area that in terms of baking into the platform we're still thinking about and figuring out. The last one is kind of exciting and it's personally very, very cool to me. We're calling it writable files but it's the idea that we wanna start giving web apps the ability to get reusable handles to files on the user's device. So I'm sure a lot of you have gone to some website where they ask you to upload a file or they offer to download a file and you downloaded it as a zip or every time you made an edit you had to re-download the file. I had to re-upload the file. It's not a great user flow. So instead what we wanna do is create a way for apps to get a handle to a file such that they can just track changes to it like a normal app would. Again, this is an area of exploration. We're figuring out how to get the privacy and security models right. But it is a spec that's available on the Wikig and we would love to get people commenting there telling us what use cases they might have for it, what concerns or mitigations they have planned. It's all on GitHub. We would love to get collaboration from everyone. All right. I hope that I've made an okay, hopefully great, case for the idea that caching with client-side storage is a huge win that you have available to you today. It's not the easiest or the first thing you'll jump at, right? Performance optimization is kind of, in a lot of ways, at least for me, when I'm developing a secondary impulse to making it look right or adding a cool new feature. But it can be a huge win and it can really translate to increased bottom lines. So it's very important. And I hope that I've convinced you guys that there's stuff that you can do via link rel preload, loading blob URLs for images, storing things in IndexedDB that work across all browsers and that you can do today and that it's not too much work to get it working. A few concrete takeaways is that storage isn't just about offline. Think about it as a performance optimization just as much, if not more.  And this is gonna go up as time goes on and it will go up when you have users who are using higher end devices, but this is sort of your bare minimum budget you have from Proving Performance. IndexedDB is for structured data. Cache storage, where it's available is for URL addressable data. And that's it. Thank you guys. I really appreciate you taking the time. Right. Super duper. Should we crack on with the next talk then? Absolutely, no time to waste. Then I can sit in the back and be petrified about my talk. Yes. You're sweating for an entire hour. Well, it's just great in the finally crafted. I can't even take this off because the shirt is quite transparent. So it's... Nobody wants that. Breaking all kind of rules if I do that. Yeah, so let's not do that. So in which case we better hand over to our next speaker. It's gonna be Seth Thompson talking about V8. I wanna know when they're gonna release V9 because it's been ages. Oh my goodness. I think I just died a little on the inside on that horrible note. Let's talk about V8 and wasm. It's Seth Thompson. Hey. Hello everybody. All right. Make sure it's set up. Okay. Hi, my name is Seth Thompson and I'm a product manager on the web platform team. I work on V8 and DevTools and WebAssembly. And today I'm gonna talk a bit about JavaScript and V8 and WebAssembly too. So what is V8? Well, V8 is an engine. It's part of Chrome and it runs JavaScript in webpages. So the V8 team has a simple mission. It's right here. It's to speed up real world performance for modern JavaScript and enable developers to build a faster future web. So really there's just two things we care about. We care about making JavaScript fast that's already on the web. And then we care about making it easier to write performant JavaScript. And that's things like our language efforts and standardizing new parts of the ECMAScript language. So what do we mean by real world web? Like what is the real world web? Well, the real world web is different for everybody. It's whatever sites you are most likely to visit. Whether it's the Onion, New York Times, pictures of cats, these are the things that people browse most frequently. So in our testing or in order to try to benchmark V8 and come up with a workload to drive our optimization strategies, we wanted to make sure we understood what this real world web was and what the performance characteristics of it were. So we set out to pick a variety of sites. We call them internally just top 25 sites. They're not necessarily the top 25 in the Alexa ranking, but they're tried to be representative of a variety of different types of sites, different content, and most importantly from around the world. Fun fact internally, we actually use Taylor Swift's web Twitter page as the Twitter example. So there's a variety of sites we use and the reason we have ended up here where we're actually measuring the performance of V8 against real web pages is not sort of obvious. It took us a while to get to this stage where we're actually using real websites to measure performance. Here's a simplified history of how we measured performance on V8. The first error sort of at the very beginning, most JavaScript VMs used micro benchmarks to measure the performance of code. Now micro benchmarks test individual language features in isolation. So you might run a loop to push an element to an array 10,000 times. That's a micro benchmark, it just tests array push. Now this suffice for a while, but we quickly realized that measuring things in isolation in a vacuum didn't necessarily yield performance optimizations that translated to real applications or real code, bulkier code. So the next error was really static test suites, things like octane, you might recognize the name of that benchmark. Now octane is more representative than a micro benchmark because it includes real code. Octane includes a Gameboy emulator actually and a ray tracer. So this is real code that people have written, but benchmarks like octane are static. So we have an updated octane since we released it. And in addition, not all websites run ray tracers. So as I mentioned earlier, Taylor Swift's Twitter page does not have a ray tracer embedded on it. So this third error was necessary because we realized in addition to the previous workloads that we used to measure performance, we needed something that was even closer to what users found when they browsed every day. Another way to think about this is that the sophistication of your performance measurement strategy is probably inversely correlated with the distance from your target. So if you're starting out and optimizing a performance problem and you are four or five or eight times slower than where you need to be, a quick and dirty workload like a micro benchmark could be all you need to just close the gap a bit. But as soon as you start hitting or getting closer and closer to your target or closer and closer to the optimal performance of something, the importance of how representative your workload is raises drastically. And that's why we find ourselves, moving beyond an era where micro benchmarks sufficed and even static test suites like octane and trying to measure against real websites. So what sort of insight do we glean from measuring websites? Well, we instrumented V8 so that we could see where it spent time, this is where it spent time in the V8 engine, when loading the following websites. For example, we run more websites as well, but this was just a sampling. And you can see here that we have a really detailed insight into what parts of the compiler and what parts of the VM contribute to the load time of pages like this. And this helped us change some assumptions we made about where we should spend our time. You can see here that a lot of websites run compiled JavaScript, or at least a lot of websites take a portion of the actual load time running compiled JavaScript.  So this was an insight that came from moving beyond static benchmarks and from looking at actual websites and has really driven our optimization in the last year or so. So I'm happy to announce actually that we've improved the median page load for the top 25, these top 25 websites we measure by 5%, which in some sense seems like a small number. But if you think about how long Chrome has been optimizing page loads, and if you multiply that savings across every time that somebody around the world accesses one of these sites, 5% is huge. It's a large, it's incredibly large savings. And the improvements on some pages were even higher than that median. Facebook, YouTube, Wikipedia, Instagram, and discourse all saw big performance improvements. And most of these came from improvements in the runtime and in the parser, not necessarily our optimizing compilers. And I mentioned that static test suites were not as representative as real web pages, but sometimes they can be useful. And in fact, we look at all of these types of workloads when we're working. And the speedometer benchmark, even though it's a static test suite, actually maps quite closely onto these real-wild websites because what it's doing is it's measuring the performance of frameworks, things like React, Angular, Ember, and we were happy to see that the performance work we did for the real websites correlated to speedometer. And so in the last six months, we've improved speedometer performance by 15% to 25% depending on the device. So that's performance, but there's many aspects to making JavaScript run efficiently on a computer or a phone. And in particular, the memory consumption of V8 matters a lot, especially on low-end devices. So these are devices with less than 512 megabytes of memory. And in fact, the number of these devices out in the wild is incredibly large. So we focused on reducing the memory footprint on these devices in particular and actually reduced Chrome's overall memory consumption by 35% by tweaking the heuristics we use and the trade-offs we make in the heap size and zone memory. So that's a big number. Another brief engine update, I've talked previously about the different parts of V8. There's an optimizing compiler, there's a baseline compiler. Well, we have been hard at work introducing an interpreter to V8. Now, you might be thinking an interpreter isn't that supposed to be slower than an optimizing compiler or a jitting compiler. Well, an interpreter has a benefit, which is that it has a lower memory footprint than an optimizing compiler, which has to compile all JavaScript into native code. And in addition, the interpreter is a simpler piece of software. So it's easier to make optimizations with a simplified execution pipeline. And we can also choose, we don't have to use the interpreter always, we can choose sort of how we tear up to full speed. So adding the ignition interpreter actually brought sizes, memory savings. But in addition, it allows us to make some improvements which made ES6 generators almost three times faster. So we're excited that this has showed real wins already. So let's talk about ES6 features or ES2015 and beyond. V8 supports ES6, ES7, and parts of ES2017 or things that haven't been actually formalized into an eqmascript standard yet. And this slide doesn't properly capture just how large of an update to the JavaScript language these iterations were. So if you've been programming or using ES5 and below, it's definitely time to take a look at the powerful features and the idiomatic features that these language updates bring. It's also time, if you look at the Kangex compatibility table, a lot of browsers have support for these features. So if you're using Babel or another transpiler, it may be time to start considering whether you can turn off transpilation of features and whether your users have support for them. So I'd also like to announce, and this is something that we've been spending a lot more time on is how V8 embeds in Node. I think Paul talked a lot yesterday about how many developers are full stack developers and the browser JavaScript environment is just half of the JavaScript environments that you care about. So as of Node 7, all of these features are available by default, with the exception of Async await, which will be in the next major Node version. And we've also been working on the performance of individual JavaScript features. You can see here that we've been working on things like spread, generators, four of arrays, and destructuring. And all of these were getting closer and closer to our optimal performance there. As well as built-ins, like object create, function prototype bind, array prototype push. These are things which are used all the time in framework heavy code and otherwise. But I wanna focus on one feature in particular which we launched recently. This is Async await. And this has been one of the most frequently requested features and most eagerly anticipated features of all of those language features on the previous slide. And that's because this code should look very familiar to you. JavaScript is inherently asynchronous and it's very, very easy to end up in callback soup. So Async and await are primitives, which when combined with promises, can turn code like this into code like this, which looks like the synchronous code you might run or write in another environment. So Async and await bring readability, they bring debugability, and they make it a lot easier to write asynchronous code in a style that maps more onto the synchronous way that you might think about what your application is trying to do. So I'd like to give a brief demo right now and I'm actually working on a little site that looks kind of like Pinterest. So let's, let me make these a little bit bigger here. Okay. And what I want my site to do is, let me see if I can make this source even bigger there. Okay, could people read that? Maybe a little bit. So what I'm trying to do is I want a site that loads on a mobile device or on a port network, very quickly with small thumbnails of the images before it loads the full res versions. So I've gone into my network tab actually in DevTools and I've throttled the network down to 4G, which actually is still quite fast, but I think it'll be enough to see the effect we're going for here. And when I refresh now, you can see that I'm loading in these blurred thumbnails and then as the full images get downloaded, I'm replacing them into the page. Now for the sake of this demo, to show you a single way, I've used the Fetch API, which definitely is overkill and is quite contrived, but what demo is not a little bit contrived. So you can see here, I'm fetching a thumbnail and Fetch is an API which turns a promise. So traditionally the way that you would handle this is using a dot then. I'm decoding the response into a binary blob and I'm taking that blob and creating a URL which I insert into some HTML and insert into the page. Then after that's done, I am fetching the full version of the image and taking the async fetch API, getting a promise back, converting the response to a blob and then inserting or updating the source of my image tag, removing the thumb class, which is the thing that blurred. So you can see here, pretty simple structure, I'm just inserting them into this grid I have. So this code is not terribly hard to understand, but it seems pretty verbose for what I'm doing and it's not quite clear to me that waiting for each of these previous then bodies to finish before exiting the next ones is quite what I want to do and I think that by converting this to async await, we may be able to make some optimizations. So how do you use async await? Well, await is a keyword which waits for a promise to resolve before the statement ends, but it doesn't block the thread. So the browser has an event loop and the reason that JavaScript is so heavily relies on asynchronous code is because the browser doesn't block on IO. So it's very important that even though your code might look synchronous and async await helps it do that, it's important to remember that under the hood, waiting for say a fetch, the promise returned by the fetch API to resolve doesn't necessarily block the main thread and that's really the power of async await. So how do we do this? Well, I'm gonna do one thing first and that is I'm gonna take these snippets of code that are creating these HTML tags. I'm just gonna make them their own function. So let's do that. This will be insert thumbnail and I'm gonna take in my image which is the string there, the name and use that as an ID that needs to be an ID on the HTML. So I'll take that as an input and then it takes a block too. So let's see, that should work there and then I can replace this with insert thumbnail and image block. Great. And I'm gonna do the same for this other code which takes my full resolution image and replaces the source of a particular image tag. So let's make a function of that, say update thumbnail and that also takes the image name so it can find the HTML object or the HTML element and the blob which it inserts there. Okay. So that makes things a little bit easier to see already. Let's make sure that things still work. Yeah, they do. Okay, perfect. So the first thing I'm gonna do here is all the await keyword, if it appears in a function, needs to, there needs to be some indication to the browser that the function has a weights inside of it or that it is following this other model of programming. So we use the async keyword to dictate that a function is gonna have a weights inside of it. So usually the async keyword just goes before the function keyword. But in this case, because we're using ES6 arrow notation here, you can also put the async keyword right in front of the parameters to your arrow function. So this is an async function now. And instead of taking a promise chain here, I'm gonna go ahead and write const response and this is the first of two responses, await fetch. So what does this do? Well, what this does is when this line executes is the fetch API which returns a promise immediately but the promise doesn't resolve until the network request for the image goes through. This line will actually await the resolution of that promise before assigning it to the response constant. But as I mentioned earlier, won't block the main thread while it does this. So the code is as asynchronous as it was before, but to a reader is a single line of sort of synchronous code. So this is incredibly powerful. To continue down the line, we sort of do the exact same thing with all of those then chains. So let's go ahead and quickly write this out and I'm gonna take my blob here. Actually I'm gonna call it thumbs just so we can remember that this is a thumbnail and this is awaiting response one blob. Great. And after that, actually then I can just insert my thumbnail with image, the name of my image and the thumb block. Okay. So already I've gotten rid of all of this code into these couple lines which just look and make a lot more sense when you're reading through things. Okay. Let me just quickly do the exact same thing. I'm gonna copy paste this and this is my second response and this is for the full image and I'm getting back the full blob from this, which I'm inserting rather than inserting, I'm updating my thumbnail. Okay. So let's quickly see if this does what we expect and does. Okay. So you can see here that we've removed all of this code with the then chains and the then callbacks and turned it into six lines of what looks like synchronous code but is really as I mentioned asynchronous under the hood. Now there's one extra thing to show here. In my promised chain, I caught errors at the very end. Now the way to do that in async and await code is as you do it in synchronous code.  So that looks and reads just so much cleaner than before. All right. Let's make sure that runs and we've successfully converted promised based then code to async await. So you can see how powerful this is but by converting things to async await we also sort of can potentially better see a problem with this and that is if we go to the network tab we can see that all of my mini thumbnails here so those are these first 11 lines they all finish before my full resolutions get fetched. Now why is that? Well, if we look at the code it's because we're waiting on the first fetch to finish before we kick off the fetch of the next function. So that's a problem. I want to actually, I might as well be fetching both resources at the same time rather than waiting for one to finish before I kick off the next one. So this is one time where async await has a little bit of a quirk and that is that what you really want to do here is kick off the fetches and await, excuse me and keep track of the promises that they return up here and then await the resolution of the promise in the proper place in this synchronous order because I do fundamentally need to insert the thumbnail before I update it. But if we do things like this instead of awaiting them inline then the fetch actually kicks off right after those first two lines complete and I'm not blocking or waiting on the resolution of that promise until the right time inline. So let's make sure this still works. It does and you can see now that the, make sure this is working. It's hard to see from the waterfall but I believe that the kicking off of the first full resolution is no longer blocks on finishing the download of the thumbnail. So that's an important thing to remember. Sometimes you want to kick off the promise before you await its resolution. Either way, I hope you can sort of see that this code is a lot easier to reason about and understand than the previous code and so if you're using promises at all absolutely you should take a look at updating your code to take advantage of async await. And async await is supported in Chrome Canary and will be in an upcoming release, the next release. So let's go back to the slides. Okay, so async await, very, very cool feature and it just really simplifies the writing of code. So we talked a lot about JavaScript but I want to move now to something that's a bit more on the horizon but promises a really powerful tool for you as developers. So WebAssembly is a cross-browser, plug-in-free, low-level language that makes it easy to run native code in the web. So there have been previous efforts to do something like this. Flash, you might even remember Java applets in the far-distant past, but each of those was encumbered by particular difficulties and WebAssembly is the first cross-browser, open, standards-based solution. So we're really excited that we're off to a good start in the standardization of WebAssembly. Now, what are the benefits of WebAssembly? Well, WebAssembly is a binary format so it's much smaller over the wire than textual equivalent. You may be familiar with Asm.js which tries to achieve some of the same goals but by using a backwards compatible JavaScript syntax. So WebAssembly is small from the start because it's its own binary format. And it's fast. And WebAssembly, you're dealing with memory and performing operations on numbers and int32s, int62s, float32, float64s in memory rather than dealing with higher-level JavaScript primitives which have their own runtime associated with them. So WebAssembly is fast and it's near-native performance. And as I mentioned, it's low-level. So it's possible to compile C and C++ to WebAssembly. And we're really excited about this because we think WebAssembly will unlock a new class of high-powered apps. If you thought it wasn't possible to run a Photoshop equivalent in the browser, it definitely is something that WebAssembly would be capable of running. So WebAssembly is designed to enable sort of high-performance computing and unlock things, not just games, but media applications and other things which traditionally have taken too much raw compute power to run effectively in JavaScript. So we have a demo on WebAssembly.org of an AngryBots game, the AngryBots game running. This is actually a Unity game that was compiled to WebAssembly. And you can see that the performance is a lot smoother than even the Asm.js equivalent. And I definitely encourage you to check it out. And WebAssembly is already implemented behind a flag in Chrome, Firefox, and Edge. So this demo runs in more than one browser. But today I wanna talk about how you as a JavaScript developer might take advantage of WebAssembly without digging into C and C++ or bringing out a compiler to compile WebAssembly. And that's because we think WebAssembly is also gonna unlock a really interesting functionality which might just be in a library. So you might be writing a traditional JavaScript web app and just use a WebAssembly module to perform some functionality which is computationally intensive. So if you're writing a progressive web app that encodes and decodes JPEGs, you could just offload the encoding and decoding of the JPEG file to a WebAssembly module and write all of the rest of the application, the user interface and whatever the features you have in JavaScript. So WebAssembly was created from the beginning to play well with JavaScript and interact just alongside of it. So just to give you a brief demo of this, this is far from an Angry Bots game but I wanted to show you that as a JavaScript developer if you receive a WebAssembly module, you don't have to really understand native code or C or C++ to still use it. So I've got an HTML page here that right now is just using this WebAssembly API because it's exposed to JavaScript the way you start and run WebAssembly is by calling a JavaScript API. So it's gonna load this WebAssembly module and instantiate it which is what we have to do to run it. So let me quickly switch over my server and let's take a look at what this looks like. Okay, so briefly before I forgot the other important thing here is to see what this WebAssembly binary is. Well, it's incredibly tiny. This is the binary representation or the textual dump of the WebAssembly module. That's all there is and this WebAssembly module does something very small. Just adds two numbers together. So I mentioned this isn't a big game demo but it should still be interesting to see how this interacts with JavaScript and HTML. So let's go to our new index here and this file. So what we've done right now is and I'm using async and await actually because all these functions are asynchronous. We fetch the module, we turn it into an array buffer and we use the WebAssembly API to compile it into a module and instantiate the module. You can think of a module sort of like an ES6 class and the WebAssembly instance as an instantiation of the class. The module can be instantiated more than once and you might want to use it in different ways. But regardless, instance is sort of the unit of JavaScript object that we're going to use to invoke this WebAssembly module. So let's actually break here and see what we get. So instance is, let me just actually log it out here and we can see it directly. Oh, I don't know if that turned on. Okay. So what we get out here is, all right, let's go through what we're loading here. It's our server on the right page. Yes. I'm not calling load. That is, wow. Wow, thank you. I really, yeah. I told you this talk was about advanced JavaScript but it goes beyond advanced to expert level JavaScript. Thank you. Okay, so we're gonna load this and we might then see some results. Hopefully, I mean, you could never be sure here. Okay. And what we get out is an object which represents our WebAssembly instance. Wow. Okay. Now, WebAssembly instances in JavaScript have a simple thing on them. They have exports because a WebAssembly module can export a bunch of different functions. So we see here, we get this object, has an exports method, or excuse me, an exports value and property and add to is a value that it exports. So add to is the WebAssembly function. Now, the important thing to note here is add to is actually native code. So again, adding to numbers isn't a particularly impressive example but you can see that from JavaScript in an environment you're very familiar with, you can easily get access to something like a native function and we can call it just like any other. So let's take this and I mentioned that all async functions are return promises, so we'll have to use dot then here but we're gonna take our instance and we're gonna call instance.exports.add to. Let's take two numbers and let's log these to the console. Okay. And let's see what happens. Ah, I keep forgetting I didn't map my persistence over here. Let's do that one more time and this is instance.exports.add to. Let's see what happens. Missing argument after argument list. Did I close this up correctly? We get 84. So you can see that even if you're not a WebAssembly developer or even if you're not compiling these web modules yourself, you can imagine a day in which instead of downloading an MPM module which is JavaScript, it provides a JavaScript implementation of something like a zipping coder or an image decoder or a PDF renderer, you could just rely on a WebAssembly version or a WebAssembly implementation of the same thing and use it with no knowledge of how it was created. So WebAssembly is currently in a browser preview period and we've announced that this is slated where the roadmap is to collect developer feedback during this browser preview and launch WebAssembly on by default in browsers in early 2017. So WebAssembly is really close and it's gonna be really powerful, not just for native developers but for developers making any range of progressive web apps with some computationally intensive code. So thank you very much, that was my talk and if there's one thing to take away it's that V8 is continually investing not just in the performance of JavaScript but in unlocking new capabilities and improving the ergonomics of writing web applications in the first place. So thank you very much, my name is Seth Thompson. Thank you very much. Well, Jake gets himself set up. Oh, he's had the worst time of late with his set ups, believe me, we'll talk about that, I get the feeling. Anyway, the browser panel is still gonna be going on in a little while, so if you've got questions and why wouldn't you, then you can submit those on the Chromium Dev Slack channel and we will pick those up and as I said before, we'll try and get through those. How's it going over there, Jake? Yeah, we're going well. Are you? Right, well, we've got, that's mirroring so we'll make that not mirror. How's it going, Paul, you can keep talking.  Like at Google I.O., you had the big stage and then everything bailed on you. Amsterdam, I think that bailed on you. Yes. Is it bailing on you now? That's better, look at that. I can see what you can see and that doesn't look good. Are you enjoying feeling, Paul? How's that working for you? I'm enjoying watching you go. Yeah, that's great.  I am, the sound in this as well. Have you got sound? You're all set? That doesn't feel good either. That didn't go well, did it? No, see, this is the thing. When I was, the last two Google talks, talks at Google I.O., I've mentioned on Amsterdam. Amsterdam has both been just in the middle of the talk, everything has just failed. So we've got these monitor screens here and when I did this at I.O., I was just going through my talk, everything was fine and then the one that has the slides on just went off and the one that had my notes on went green and then all of the colors in little squares and I was like, well, the notes are gone. I'm just going to slowly turn around and hope my slides are there and there was a big black screen up there. And you can watch the video back and it's like, I just kind of go, oh, I just got to go to the laptop, right. Speaking of which, though. And so what, yeah, basically what you're saying is while we might not realize it, it's a huge goal, a landmark if you will, if it gets through this presentation out without a massive disaster, at least technologically. So without further ado, since you seem to be ready. I think so. A massive round of applause for my friend, Jake Archibald.  And the new thing is the service worker. Actually, I think this is the first talk on it. There's nothing to play with in the browser yet. So this was before anyone had ever written a service worker, there was nothing in the browser at all. But now we have like two fully independent implementations in Chrome and Firefox and that means we get the other Chromium browsers come along for the ride, things like Opera and Samsung and Internet and others. Microsoft, they're working on their implementation now, it's a high priority and bits and pieces are starting to land in their insider builds as well. Savari still haven't made a public commitment, but they have been given implementation feedback on the spec so they've been looking at it in a lot of detail and they've been implementing the Fetch API as well, which is a big part of it, it's a prerequisite if you are gonna implement service workers. But thanks to the progressive enhancement, we've gone from having nothing in any browser to hundreds of millions of page loads handled by a service worker every day and that's just in Chrome. And I'm not talking about service workers that are just there for like push messages and things because there's loads more of those as well. I'm talking about service workers that are actually handling Fetch events like page loads. So that means that today, which I couldn't back in 2013, I can stand here and talk about actual shipped things because in 2013 I basically made stuff up for 30 minutes.  It's great. But I don't know. Look how happy I look there, not wearing a suit. Thanks, everyone. Oh, to anyone who's watching this in the video in the future, they voted that I had to wear a suit for this and it's horrible, thank you everyone. Anyway, but this talk, I enjoyed this talk, it was a bit of a laugh, so I'm gonna do it again. Because a lot of stuff we're starting to implement or starting to think about in service worker land and I'd like to share it and sort of see what you think about it, which things you want in the browser right now and which things, not all that bothered about. I probably should have called this talk seven things that don't so much exist right now, but I'm pretty excited about and you might be as well. It's gonna be a journey to the future. This is a real FAQ page for a train company in Wales and it's just this one question that says, can I buy train tickets for future travel? To which their answer is, yes. I've been to Wales before and it definitely feels like time travel. Maybe not forwards. So what have we got coming up? Okay, so we've got streams. I love streams. And there's a lot of streams already in the browser. You can fetch a URL just by fetch and wait it like we saw before. Get a reader for the readable stream and then we can sort of set up an infinite loop and we can call reader on the reader. And this gives us an object back which is very similar to what iterates return. There's two properties, it's done and value. If done is true, we're done. And otherwise we've got the value. And I think this code could be nicer. I always get very nervous about kind of wild true code. I mean, this works, but I don't know, it makes me nervous. And that brings me to the first future feature that I want to talk about, async iterators. Now, I have learned from my mistakes in 2013. So this is the vagueness graph. And I'd say async iterators are about this vague. But do bear in mind that this graph is itself about this vague. And that's quite vague. I hope that clears everything up. Async iterators, they're being specced right now. They're at stage three of the ECMAScript process. So we can expect some implementations pretty soon. So how do they actually work? Well, instead of this while loop and getting a reader, we can just do this. It's much simpler for a wait value of stream. And it works just the same way that our wild true loop worked before. And when these land in JavaScript, we'll start to see DOM APIs updated to use them. And so thinking about things like the cache API, you can have an iterator to go over caches, or over items in caches as well. I'd love to see this added to index DB curses for going through an entire data set. If you want to know more about async iterators, that is on the TC39 GitHub page, I will tweet out all of the links I show in the talk. But if you can't wait for that, you can play with them today using Babel. This is it running here in the Babel repel. I'm only showing you this because I have an excuse to say Babel repel, which is very satisfying Babel repel. I really love the way we name things in the industry. We just don't care. I mean, look at this. This is a totally legitimate sentence in our industry. My tiny Yelp clone, built with Redux, is now up on Ember twiddle. My tiny Yelp clone is now up on Ember twiddle. I love it. I should have put it on Babel repel when we completed the set. So when you stream values from fetch, each value is a hue into eight array of bytes. But often you don't want bytes. You want some of a format like text. And you can actually do this today using the text decoder. So I'm gonna get the new text decoder there, loop over the stream. But this time I'm gonna pass every value through decoder dot decode. Now instead of logging bytes, it's gonna log strings. But having to call decode on each value, I don't know, it's a bit of a pain. It'd be nice just to have a stream of text. And that's gonna be a lot simpler thanks to the next feature, transform streams. Transform streams, I'd say they're about as vague as asynchronous, maybe a little less vague. They're still being specced. There is a sort of JavaScript implementation, a proof of concept. And some implementation is happening in Chrome right now. So before we introduce the decoder, we are streaming stuff from the network straight into our log. No, okay. Trans... Thank you. Transform streams become this little bit that sits in the middle, that takes the fin and puts something else out. In terms of code, they look like this. You transform stream. And then you pass in an object of methods like start, called straight away, transform. And that's called every time a chunk is received and then flush, which is when the incoming stream has ended. And what you get back is an object of two properties, which is a readable stream and a writable stream, the input and the output. And this works really well because you can pass just one of those bits to another piece of code without passing on the whole transform stream. So we wanna create this text decoder as a transform stream. We'd start off by creating a function that's gonna return it, set up our decoder, the internal implementation, return a fancy new transform stream. We only need the transform function. And in there, just every time we get a chunk, we're going to do controller.onQueue, which is passing a chunk out. And we're gonna call text decoder.decode and pass that chunk through. So if we go back to our fetch code from before, that was logging out bytes. We can change this sort of around about here and we take our stream and we pipe it through the decoder we just created. And this, the pipe through connects the sort of writable, the sort of readable house puts into the transform and returns the readable of the transform. So now all these, the logs will be texted at this point. Now, like async iterators, once this lands in the browser, we'll start to see them appear in the DOM as well, sort of APIs will be changed. Things like compression and decompression. There's a lot of that in the browser already, like GZ, et cetera. Image encoding and decoding, they already exist too. They're just not exposed to developers very well and they'd be perfect for transform streams. But the first DOM API that is going to become a transform stream and we've wasted our time by recreating it is gonna be text decoder. So that's gonna be changed, backwards compatible way to be a native transform stream. And once you do that, you'll get stream out of the stream. So if you wanna dig into streams a bit more, check out the spec and that's where you'll find the JavaScript implementation. I'm really excited about streams landing in JavaScript in case you can't tell. I think it's about time because streams have been behind the scenes of the browser for like 20 years. If a page is well built, you'll see it rendered gradually. And this is because the browser streams the content from the network and passes it through the HTML parser, which supports streams, it can process it as it's arriving. Wiki offline, this is a Wikipedia PWA and it makes good use of this ancient browser feature. On a low end device, a 3G connection emulated in Chrome anyway, with an empty cache, the HTML takes around about, you know, just under five seconds to download. All the while that's happening, the parser is processing what it receives and that means we get a first render in sort of less than half a second. I think the Chrome's throttling is actually quite kind here on a real device that would be a bit later than that due to SSL setup. So at this point, we're just displaying like the top banner, the title, we haven't got the full page of content yet, but at least the user feels like something's happening. And then at 1.8 seconds, we get the first page of content rendered and rendering continues as most is received. As an experiment, I also built Wiki offline as a single page app, which is a popular pattern with JavaScript frameworks. So here, I'm just going to return this, a little bit of HTML, and then letting JavaScript handle the rest. This actually changes the story quite a lot. The HTML fetching and parsing is way quicker because there's not a lot of it. And then here we get the first render, just the shell. So at this point, performance, it's neck and neck. But while this is happening, our JavaScript is downloading and that needs to execute and then it fetches the actual content it needs for the page and inserts it. Now we get to content render, like almost two seconds later than the server rendered version. And I'm being kind here, I think. We regularly see single page apps taking a lot longer than this to get content on screen. It's a little bit of a misleading graph because it looks like the single page app completes everything a lot sooner. The reason for this is in the server rendered version, as it's downloading the HTML, it kind of discovers things. It discovers things like style sheets, images, fonts, all of that stuff. And it starts going, oh, actually, some of this is important for the top of the page, so I'm going to devote bandwidth to dealing with that. In the single page app version, none of that can happen until that content is parsed and that happens right at the end at that render there. So it's load slower. What can we do about this performance problem? Well, we can bring in a service worker and we can store the actual page in the cache and so that makes that a little bit shorter, that download time goes away. We can do the same with the script as well. But the page content still comes from the network. You know, we can't cache all of Wikipedia. The problem we have here is that JavaScript initiates the content download. So we have to wait for the JavaScript to run before we can start fetching the content. We can avoid this using link role preload, which we saw earlier. So doing this means we can sort of run those two things in parallel. But so what? All of that optimization later, like a service worker preloading caching, was still slower than the empty cache server render. So just to let you update for everyone, the screen of my notes in just went off for three seconds. If this could be happening again. But we're still slower than the empty cache render there and that's because we're spending all this time downloading content and then not doing anything with it until we have all of it. So we've traded this gradual rendering model here for one where we just display nothing until we have everything. And it's just because there's no API that can take a stream of HTML and inject it into the page. And we really need that. I hope we get that one day. But until then, we shouldn't be breaking performance by using a single page app, then just trying to limit the damage. We should be taking the well-performing server render and then making that even better. And streams combined with service worker, let us do this. So like we saw before, this streams. The same is true if we put a service worker in the middle. It doesn't really change anything. If the content is coming from a cache, it will also stream, which is still important if it's like a large video file. You know, you still want that to stream from disk. But ideally, we want a mixture. So we want to serve a single HTML response where parts come from the cache, the static parts like the header, but the dynamic parts come from network. And you can already do this in Chrome. In the service worker fetch event, I'm gonna get three parts of the page. I'm gonna get the start from the cache, the middle from the network, I can sort of include, and then I'm gonna get the end from the cache as well. Then I'm going to get readers for all of those because we're gonna process those streams. I'm gonna create my own readable stream and I'm gonna make a response using it so I can just pass the readable into new response and off it goes. Unfortunately, populating that stream is not so easy. It's like this, you know, it's a big bit of code. It's, I'm not gonna talk through it. It's quite ugly and it involves passing every chunk sort of through JavaScript and sort of dealing with it and processing all of those streams in order. This is actually gonna get a whole lot easier thanks to identity streams, which is the next of the 2017 features I wanna look at. I would say these are more vague than transform streams mostly because the API changed less than two weeks ago. So, you know, things are moving around but I think it's pretty stable now. To use this in your service worker fetch event, just as before, I'm gonna get those three parts that I'm going to display but this time I'm going to create an identity stream. An identity stream is just a transform stream that doesn't do any transforming. The input just goes to the output. So I'm gonna respond with that readable part of the transform but then before I do that, this is how we deal with the writable. I'm just gonna do something asynchronously. So I'm gonna have a self invoking async function there. I'm gonna, for each of the responses, promises that we have, going to pipe the body to the writable. I'm gonna say prevent close here, which is just saying, hey, once all of this stream has gone into that stream, don't close the other stream because we've got more to do because we're gonna do for each stream and then we can close it out. And that's it. And not only is this code simpler, it's also faster because we're no longer passing every chunk through JavaScript because the browser can go, oh, hang on, like the stream that we're receiving is from behind the scenes. It's either coming from the network or the cache. And then the thing receiving the stream is the HTML parser, which is also behind the scenes. And it can just do the whole thing in the background and save a whole lot of processing time. So now we're getting the best of both. We're responding quickly from the cache but streaming the rest of the data from the network. And the result of that, so here's where we were before, we can optimize our server rendered version with the service worker in streams. The parse starts earlier because it receives that big lump of content straight right at the start from the cache. And this means our first paint happens much sooner, but the important bit is the content happens way sooner. So we get that quick offline first cached render but still the benefit of the streaming render for the uncached content. So it's now over a second quicker for content than the hacky single page app. And with a model like this, I'm actually kind of happy with full page reloads when it comes to navigating around. So on the left here, I have a single page app. So every time I click a link, JavaScript is going to fetch the data and put it on the page. On the right, it's just a webpage. You click a link, it's going to reload and it's going to load that data. So I set them off at the same time. You can see that with all the complexity I added with making this a single page app and using push data, et cetera, it's still slower than full page reloads, especially when they're supercharged by a streaming service worker. Your mileage may vary, it can depend on the amount of content you've got, but I'm not making this up. Although this is a demo, I actually got hit by a real-world case of this only a couple of days ago. On Monday, I was at Heathrow Airport, browsing GitHub on airport Wi-Fi, which is not so great. Now, GitHub will use push dates and it will use JavaScript for all of its navigations. Unless you're in a new tab, then it will do a server render. So what I'm going to do here is I'm going to click a link on the left here and then I'm going to paste the same link into an empty tab. So here I go. Click the link, paste it, off we go. And we can see that the server render wins by a country mile. It's way faster and this is not throttled or anything, well, not artificially, this is just airport Wi-Fi. And this is because on the left, it has to download everything before it can show anything. At GitHub here, they've written a lot of JavaScript to make this quite slow. Unfortunately, all too often I hear people say that a progressive web app must be a single-page app and I am not so sure you might not need a single-page app. A single-page app can end up being a lot of work and slower. There's a lot of cargo quilting around single-page apps and I know what happens when you just sort of copy someone else without really understanding the situation. You see, I went out for a meal with Paul Irish. Yeah, that's right, for the meal with Paul Irish. He wants to touch me. Anyway, I watched Paul taste some wine. This is amazing. He swilled it around in the glass and he took this huge sniff, like a huge sniff and then I said to him, I thought, wow, Paul is so cool. Like, he really knows what he's doing. This is amazing. And anyway, a couple of months later, I was back in England, out with some friends and we were at a restaurant and we had some wine and I thought, I've got this. I know what to do here. I've seen this done. So I took the wine, I swilled it and I took a big old sniff. But I took the wine glass just a little bit too far and dipped my nose in it. Don't know if you've ever snorted wine before. It is not pleasant. I just kind of sneezed it out everywhere and my friends were just staring at me covered in a wine mist. I'm like, Jake, why didn't you just drink it with your mouth, even so much easier? The moral of the story is, you might not need a single-page app when it comes to, you know, there's a link there. You know, a server render might be enough, especially when you've involved the service worker. And of course, if you're using a client-side framework, server rendering is an absolute must. I mean, React, Ember, Angular 2, Web Components, they all let you get something on screen in a streaming manner before JavaScript fetches. Just make sure you're not displaying things that should be interactive but aren't. So things are looking pretty good. However, Facebook had been prototyping with this stream stuff and identified a problem. If you're serving from a service worker, there is the startup time of the service worker to consider. And that's zero if it's already running. But the service worker shuts down if it hasn't done anything for like 30 seconds to preserve memory. Depending on a user's device or other things going on, that startup can add, in the worst cases, a few hundred milliseconds. And that delays the content fetch just by a little bit. And we are looking to reduce that startup time. But it's always going to be more than zero if your service worker isn't already running. Are we just going to live with that over my tiny Yelp clone we are? So we're going to introduce a navigation preload. Now, I would say this is a little higher on the vagueness scale. We have an implementation in progress, but the spec is still kind of moving around a little bit. So take this with a grain of salt. Our goal here is to start the HTML fetch in parallel with the service worker startup, which you can enable just using this one line here. And you can do that whenever you want, but the service worker activate event is a pretty good place to do it. And this means for navigation requests, the browser will make the request to the network while the service worker is booting up. That response appears on the fetch event as a preload response. And that's a promise, and that will resolve if undefined if it's not a navigation or if the feature isn't enabled. So it's always worth looking in if it's falsely just do a normal fetch if that's what you're wanting. Now, what you do with this is up to you. You could respond from the cache and fall back to the network. But given that this preload can happen pretty early, it becomes realistic that the network may beat the cache API. So why not race the two of them and see which one comes back first? I'm going to pick up on a point Soma said yesterday, because he was very right, that promise.race is not your friend for doing this at all. When you give promise.race an array of promises, it takes the result of whichever one ends first, not whichever one succeeds first. Like, take this race. There's a race. I'd say this race was in progress, because no one has won yet. Promise.race, on the other hand, would say, she fell over. Don't care about anything else. The whole race was a failure because of her.  So you will need to write your own racing function here. You wanted to resolve with the value of the first promise and resolve with a true value, but it's a few lines, but that's what you need. But what about our streaming code from before? A straight up preload wouldn't work here, because we're not fetching the same thing that would be fetched if the service worker wasn't there, because we just want the middle of the page, just that middle bit, because we've already got the top and the bottom in the cache. Thankfully, this is not a problem, because those preload requests are sent with a special header, this header here. And if your server sees that, you can go, oh, OK, I'm just going to serve the middle bit, because this is going to go through the service worker and it knows how to deal with it. So back in our code, we can deal with that. Just right here, use the preload response if it's there, otherwise falling back to fetch. And that means for navigation requests, that will happen at the same time as the service worker's booting up. And this is something that we can improve on even more. With this feature, we can potentially look at doing it as the browser is booting up, which is particularly good for progressive web apps added to the home screen. And we hope we can get there as well, as soon as the user presses it. Just as the browser is booting up, we can have that request started well early. If you want to dig into this a little bit more, there's a huge thread on GitHub about it. I'll post the links later on. What else have we got? Ah. So the current way the service worker works is that request from your page will go via the service worker, your service worker. And that happens even if the request will be different origin, like a font service. Your service worker decides what to do. And this is by design, because it means you can cache things that like images and fonts, even if the destination server hasn't even thought about how that would work or how to do that. The downside to that is many sites may end up with the similar logic for font caching or analytics and can end up storing the same thing independently. And in the future, we could look at ways of deduplicating that inside the browser, but the logic is still being duplicated. So to the rescue here comes foreign fetch. So I would say this is a little vega still, only because I'm pretty certain parts of this API are going to change. But there is a version of it in Chrome Canary already, which you can actually test with real users. I'll put a link up on how to do that in a minute. So what is it? With foreign fetch, the font service has its own service worker in storage. And if you make a request of the font service, it first goes to your service worker, and you get the first shout of what to do. But if you send the request on to the font service, it goes to its service worker. And they get to decide what to do, which could be to get the stuff out of the cache and send it back. So that means now if another website makes the same request to the font service, it can get that caching benefit the same resource that the font service has cached. So if you wanted to do this, if you wanted to be the font service and make this work, in your service worker you listen for this new event, and you're triggered when another origin requests something from your origin. And from there on it's kind of a little familiar, you know, respond with what you're going to respond with, however you want. Let's look to see if there's something in the cache otherwise fall back to the network and then return the response. And this is where things get a little bit different. Rather than just returning the response or a promise for the response, you return an object which has a response property. Now when you do this, the destination server will not have scripting access to the content of that response. It won't be able to get the text of it, but it will be able to include it as a script tag or as an image element or something like that. The same way cause works today, this is like a no cause response. It just won't be able to get at the text or the pixel data of the image. If you want the server to have that access, you add the origin property and you set it to the origin you want to have access. If I have visibility to this resource, I want them to have visibility to it as well, which you need to think carefully if that's what you actually want. Otherwise, you can set up some kind of whitelist or something. You could even sort of get this information from index DB. You're coding, you can do what you want. So this is kind of a representation of cause but with JavaScript. So you can sort of do a lot of different things. We talked about font and image APIs and analytics, but you can use this to create whole REST-like APIs that work entirely offline. One detail that's missing though, how do we get this service worker installed on the user's machine because if it's like a REST API or a font service like where the fonts come from, the user's very rarely going to actually go there and that's when the service worker is installed. So to fix this, when you actually give a resource to a page, you can also serve it with this special header which tells the browser about the service work you have and it will then go and install it. If you're keen on foreign fetch, article by Jeff who was speaking earlier, he covers it and he also covers how you could actually use this on websites today as part of an origin trial. Oh yeah, so earlier on, background sync was mentioned, which is a feature we shipped many months ago. It allows you to defer single tasks until the user regains connectivity. So say the user updated some setting in their profile or sent a chat message when they had no connection, background sync lets you queue that work and now the user can sort of navigate away, they can close the browser and later once they have connectivity, the service worker can wake up and send that stuff to the server. And this is shipped in Chrome like it's done and it's great for small bits of data, like profile updates, sending a chat message, that kind of thing. The problem here is like while the sync happens the service worker has to be awake the whole time and that's bad for privacy and bad for battery. So we're not going to do that. What we do now is if a sync runs for too long we just kill the process. But for large uploads and downloads we're working on something else, background fetch. Now it's quite early days for this one so it's pretty vague. Vaguer than the vague graph itself so it's quite vague. All we have right now is a kind of API sketch and we're starting to explore the issues and then we're going to work. It's a cross browser effort. So here's the idea. From your page or your service worker whichever, you get hold of the registration and then call background fetch.fetch give it an ID and then give it some requests. So for a movie this could include like the video resource but also like some metadata or something, poster image or whatever. And that's it. That fetch will now happen in the background as well. Once the fetch completes you get an event for it and that will give you information about it. You can start having a look what's the tag I'm going to actually cache this stuff so I'm going to open the cache and then event.fetches will be a JavaScript map of requests and responses that arrive so you can do what you want with that. Of course if you're uploading photos you don't want to cache the results you'll just maybe show a notification so you've got the freedom there and during the fetch you can show the progress of the download and because of this high visibility and it being easily cancelable we're hoping that we can deliver this feature without any sort of permission prompts we just need to make sure the privacy aspect is correct and make sure it isn't too abusable. Is this something you're interested in? You can take part on GitHub I will move that repo somewhere a little bit more neutral like the YCG the standards thing. Oh yeah earlier on I showed you this thing here the full page navigations being significantly faster but I know why people go down the SPA routes because they want to do a nice transition from one state to the other it makes me sad because I've seen developers introduce large frameworks just for basic transitions which is a little bit of a shame especially to have to reinvent the entire navigation stack just because you want a nice fade from one thing to another and that's why we're going to take another look at transitions I mentioned them yesterday I really want to have a good plan for this in 2017 but right now the idea is very very vague in fact we have to scale the whole graph down just to sort of see the top of it so take this with a big bag of salt and it's not the first time we've looked into this either Internet Explorer 5 you could use this meta tag to specify a kind of enter or exit from a set of configurable presets so with this page in Internet Explorer 5 the user would click the link and Internet Explorer would crash is what it usually did that was my experience anyway but in 2014 Chrome Dev Summit we pitched this transition's idea we showed demos I didn't really pan out Mozilla have a proposal as well but they're both solutions so I can kind of declaratively say I don't think they're expressive enough stuff like this should be possible and that would be a full page reload utilising the full navigation stack of the browser and the streaming HTML parser because when you do this you get the back and forward buttons working for free if we actually take a closer look at this transition the first part we can do that without any additional data we already have the image we know where it's going if we have that title already stored we can do that bit and we can improve the perception of performance by doing this bit while the actual fetch is happening and then we can bring in the content once it arrives and if it arrives while we're transitioning we can bring it in earlier and sort of make it part of that sliding transition the transition out's a little bit different and we actually need more data to do that transition because we need to know where we're sending the clock back to which depends on layout the scroll position I really think we need an API that allows this something like a navigate event that fires when this page is going to be changed and you can say hey, I'm about to do a transition so keep this document around for a bit and at this point you can start doing the very first part of the transition like you're getting everything into place where you think things are going to be get hold of the new window object which will represent the page that's coming in and that will resolve if undefined the cross-origin navigation I would like us to look at cross-origin navigations as well but they have to be pretty restricted for security reasons but once you've got this new window you've got scripting access to it you can start doing what you want by default I think the new window will draw on top but the transparent parts will show the page underneath so here you can start looking at where elements are what the scroll position is here I'm just going to set the opacity to zero of the new document interactive and then fade that document in so that's a simple fading animation this is a simple example but it's as complex as you want to make it so with this you'll be able to do these expressive animations but retain all of the features the browser gives you for free in navigations if that's interesting to you the details are on GitHub I intend to move this repo somewhere a little bit more neutral the term progressive web app is just over a year old but the work has been happening for years on this stuff and we're not done I think you've heard over the past couple of days how much we love the web and where we want it to go but now it is over to you we want your feedback on this stuff be it in GitHub at the very early stages or playing with this stuff in Chrome Canary so come and talk to us about it I can't put it better than this shop window sign we're not till not happy wait we're not happy till you're not happy no that's not it till, oh no I don't know anyway thank you very much well done buddy I've got to say even though I knew it was you I was like that butler is really well informed I was like wow he's really excited about the future of the web you feel better now apart from the three second outage did you have anything else go it was just enough to give me all of the nerves good excellent excellent well it's time for the big web quiz to come back but obviously we're just waiting for an AV I was excited about the iTunes the terms and conditions that just appeared that was enjoyable that looks good and might as well press F there we go just say don't ask again that will do it well done these are not the final questions of the day are they no we've got a little bit more there's still time to to win so if one gets logged in and we can do a couple of questions are you feeling good? oh yeah my wifi is working excellent you ready? which one would you want I'll do the cause one do you want that one first here we go then this should be appearing at some point never oh here we go of course in a request to another origin what can you set to the content type hang on what can you set to the content type editor that's a bit bizarre mate what can you set the content type editor without incurring a cause pre-flight without incurring a cause pre-flight multi-part form data application XML application x-w-w-w form URL encoded which is of course very long I can never remember that I'm feeling it's like the dream weaver default actually when you made a form interesting now it feels like the audience oh they're very confident on the 67% there oh yeah two thirds oh no so what are we seeing here so we're thinking probably not application XML the conflict with the text plane they're thinking you know pretty solid not that comfortable with multi-part form data pretty confident with text plane interesting let's find out which ones are correct interesting and the reason for this is all of those free you can do with an HTML form you can set the content type to one of those so it's kind of like hey you can do it already so you don't need a pre-flight for it application XML well feels wrong to say XML is new for fun for this it is right should we do another one yep we got time here we go this is a fun one what is the prototype of this custom element before its class is registered is it HTML element HTML unknown element or HTML pending elements I've got a feeling this audience really knows this one well there's definitely an unpopular answer yeah but the other one is the other two so it's basically pending element pretty much disregarding that one as not a thing but unknown element versus HTML element the correct answer is it's unknown element until such time as you tell the browser and it used to be document dot register element it's now custom window dot custom element dot define for v1 no until that point it's unknown and then it becomes whatever it's supposed to be right I don't know who's on next so you have to do this wait to see if you remember Patrick it is in fact Patrick Kettner coming to talk I believe about the progressive keeping the progressive in progressive web apps ladies and gentlemen Patrick Kettner hey everybody how's it going good happy to be almost done or happy sad it's over anyway I'm here today to talk to you about in progressive web apps my name is Patrick Kettner unlike what it says on my badge apparently they thought the Chrome team needed another poll around but my badge is right I do work at Microsoft despite what my t-shirt shows there I'm just a conundrum of confusion it's just a photo I take every year for my birthday I get these pictures of cakes every year my incredible partner Katrina hi if you're watching is usually here with me she's been spending a lot more time at home because we just had our first child Holden was born thank you very much it's he's worth the applause I know I'm pandering a little bit but he's a really really cool baby it's funny when you when you first have a kid all your coworkers all your friends all your family give you the same collection of advice they all say enjoy your life while you still have one or you know have fun eating while you can still have time to do it or have fun sleeping while you still are able to and it's funny because with Holden none of that really applied he's been a super easy baby he's really cute all the time and he's just happy literally happy all the time he's fine now but he got sick and had to go to the hospital and he was adorable in the hospital this is him with a fever and is sick and everything he's a crazy happy baby he's cute all the time and that's when we go on drives he hates getting into the car seat not so much the drive itself but like being strapped in he just I don't know it doesn't like being like not able to move or something and he just freaks out and that's fine when you first bring him home we like literally live a block away from the hospital he was born in and so we walked home like we didn't have to drive it took us a while to discover that he hated this and you know it's fine and then after a while I love to travel and you know Katrina puts up with me liking to travel and we have sitting at home getting a little cabin fever and so we thought we would pack up and go visit Whistler which is outside of Vancouver, Washington I work at Microsoft so I live up by Seattle and you know knowing that he hated being in the car seat knowing he'd have to go into the car seat and being a nerd I do something that I think most of us would do and I go and try and find out something online that's how to make it better and so I look up how can I calm a baby look at all these different ways that people suggest doing it's my first kid and I found this really neat video the frame rate is going crazy it's usually slower than this but it's basically this interesting thing all it is is a video of dancing kind of dots and it snaps him out of it like that every single time and I'm not quite sure what the science behind it is but effectively just the combination of the contrast and the motion it just instantly he forgets why he's crying and he's just like oh crap there's all kinds of stuff and you know he just keeps going literally works within seconds every single time and so I'm like oh sweet great got it put him in the car freaks out show him the video on my phone two seconds later he's fine passed out and we go get in the car head up to Vancouver it's a beautiful drive if you've never been Pacific Northwest is where it's at we have a wonderful day in the Whistler area it's a great place to visit we go and see the old Olympic stadium that's him still sleeping after getting there those dots really work and you know we're there for a few hours ready to go on door car and I strap him in and he starts he wakes up as soon as I put him in obviously and he gets really upset as soon as I do it and so I'm like ah got you this time pull out my phone my phone carrier I have like free international roaming I hit play and I get this and I get this and a baby's crying and my partner Katrina is starting to get upset because it's been a good two minutes now where I'm just standing at the phone and I'm like it's coming don't worry and I wait and I wait and it's been five minutes literally five minutes standing at this screen with a baby screaming getting more and more upset and Katrina getting more and more upset and me getting more and more frustrated because I don't know about you guys but as a person who works with technology especially like web related stuff when the web fails me I take it super personally I'm like I could have done this better something you did was stupid and you know the whole time you know eventually we're just like you know whatever I'm just going to pack up and he'll I don't know cry and he'll be fine and so we just hit the road I'm just getting more and more frustrated and I'm like just 2G just completely ruined my day that we had a nice time but this my phone is just so frustrating and then you know I started to get eventually he cried himself to sleep and I was driving and I'm like you know it wasn't like the 2G that ruined my day because that could happen to anywhere there's nobody there's you know like YouTube can't send everything in like one bit or whatever it was really the fact that it was 45 megabytes of this video and I was super lazy I went out I found a solution and it worked really well on my machine on my incredibly fast home internet and it functioned and I was happy with that without thinking about the facts that it's shit for a ton of people out there I was it's it really really sucks when you're in Canada on 2G and you have no way to load this sure I could have like pre downloaded I should have done a lot of things to make it better as an end user but I couldn't have expected that to happen and so eventually we get back over the border eventually he is able to be calm down again we get back home and you know I sit down still frustrated with having been disappointed in myself for being a lazy engineer and so I do what I feel like a lot of people do is I sit down I open my text editor and try to make a better solution because we're JavaScript developers so we re-implement stuff and so I open up my text editor and I open up Vim and I'm ready to go and then I realize that I'm terrible at anything visual you know I'm like the maintainer for modernizer I can JavaScript around tons of people all the time but anything visual related I'm just horrible at so I'm like it's fine it's just a bunch of dots dancing and then I have like I have no idea how to make that happen like I can put a dot on the screen I can do a basic canvas or something like that but I don't know how to move stuff and so I sit and I wait and I wait I have no idea what to do and so Rise Man once said when you don't have a better idea you can buy a novelty domain that's exactly what I did and I went out and I bought hush little baby and in that time that it took me to come up with this hilarious domain name I was lucky enough to put out a tweet on there saying like does anybody can anyone explain how to do this and Sarah Soudian and I'm sorry for pronouncing it wrong Sarah I'm trying hard though I said like oh you should check out green sock and if you guys don't know green sock is a phenomenal animation library it's kind of like a jQuery for animation but ignore the jQuery animate part it's really really good it's super performant it's super fast it works really great for javascript type manipulations and it worked and I was like holy crap I got this whole thing working literally within like an hour it was less than 6k for the initial rendering and the initial animation I lazy load in a like an mp3 file so it gets you know up to like two megs or whatever but that's fine and it works incredibly fine I did a service worker obviously because I didn't ever want to be stuck in Canada with a crying baby again and you know it's a super simple service worker this is one of the first ones I ever shipped in a personal product and I was happy with how little code it was you know I do obviously a feature detection for service worker and then this was basically our entirety of the service worker it's just a simple like a pre-cache step so obviously on our install we grabbed that event we have our array of URLs of files that we will definitely always have and then we grabbed that event we open up the cache that we have for it and then once that resolves we prefetch every single one of those with a simple request we put it in our cache and then we just also have a very simple fetch step where in case I add something to the domain later and I don't add it to the prefetch step it's just you know automatically added there as well we check to see if it's in the cache and if it is we respond with it and if it's not we fire off another fetch it's you know really it's literally that's the entire content of our service worker just transpiled out of ES6 and it was great we had all this like super smooth working stuff I was super excited because you know Holden got upset because he ran out of a bottle before he finished it because he eats a lot and I picked up my phone and boom and he stopped and I felt like super dead and I was so excited I ran over I showed Katrina she was excited you know because you know it's a bait no one likes a baby crying you want him to feel better and so she takes him into his room later and he we're in an old building for America I know I have British friends who make fun of that but it's like a hundred years old which is ancient for Seattle and it's like thick brick walls and everything and so in his bedroom there's a terrible cell phone reception and so she's like he starts crying I put him into as she's putting him into bed and pulls out her iPhone and then she goes to open up the phone the app and gets this crap once again I felt like it just an absolutely terrible you know problem solver this same problem happened just because I had made it work perfectly on my phone for my one solution and so the problem is that it had no iOS support as we all know service worker support within iOS and so I had to sit back and think about what to do and a wise man once said when you don't have a better idea try out appcache and yes that appcache it's terrible it's terrible it's awful I'm not suggesting that people actually super try it out but what I am suggesting is that you don't immediately discount technology that you hear is terrible there is a lot of stuff that browsers have been shipping for a very long time that might be able to meet your solutions I work at Microsoft I hear about old crap all the time stuff that we've been doing in IE5 that is just now coming like Jake mentioned the navigation transitions there's all kinds of stuff that we did a long time ago that might still be useful occasionally it's worth checking out the very least it's worth knowing what we did wrong on these old specs like applicationcache and in this case what I was doing oh yeah actually it's so bad that it's being removed from HTML I don't know how many things you know of that are actually actively removed from the HTML spec but this is one of them we all agree that this is terrible and needs to just be purged from our collective memory but appcache is incredibly well supported across the board as long as you're not developing for like opera mini or god forbid old IE like you are pretty much guaranteed to have an appcache support and for a site that's as simple as the one I made which is obviously much less complex than I'm sure most of the things you guys would ever make it's really really straightforward and actually feats all of our use cases and so we just take our feature detect from before and we add another little feature detect I don't know a lot of people actually have never used applicationcache and so you might not be aware that in order to use it it's actually an HTML attribute that exists on the HTML element and that has to be there at the very top of the page at load time you can't like dynamically injected it's not again it's a horrible API it's a giant douchebag the attribute has to be there at crush time and so in order to get it to the bottom of the page you have to bend over backwards and do it this way and so inside of this check what I end up doing is creating an iframe hide that iframe and then it's give it the source attribute of like a specific page that only loads loading an appcache it basically just has that attribute and then I append that at the bottom of the page is the entire contents of that HTML document it's super super small does almost nothing but it gets that appcache in there and it starts downloading all the assets and so those assets that I have in my prefetch cache and through like a little webpack transform turned it into a web manifest or an appcache thing out of there and cache manifest is a really simple file format that's one of the reasons why it's terrible it's because it's super like if you do this one thing it makes sense and nothing else so we have the cache manifest and then the files that we had before and then we also have to have like this network star at the bottom the reason for that being that appcache automatically assumes that it knows everything and any URL that is not on this list will automatically 404 even if you're online it's a terrible API it's really really crappy but if you know this edges and if you know what to do and how to get around those problems it can be useful check out crappy apis because there might be like a little glimmer of something useful inside of it it is a douche bag don't forget that but check it out don't immediately assume that just because you heard a technology whether it's something built into the browser or a library or anything else is terrible just because you heard it's terrible find out for yourself and learn um in fact I was thinking about while I'm doing terrible ideas I was remembering when I very first started in websites and we had this anybody remember DHTML anybody ever have that on the resume yes thank you yeah does anybody ever write an HTA a hypertext application thank you thank you thank you yeah so I made it into a hypertext application as well because why not and so what I did was after all those text checks I shipped this as a I checked to see if it's an old Microsoft thing oh I'm sorry a hyper HTA or hypertext application is a proprietary offline application shipped in Microsoft Internet Explorer 5 it's terrible um but but it exists and I figured I was already doing stupid shit anyway so I want to have some fun so if you go to this website hush little baby and IE you actually get this huge pop up because there's no reason to be using old IE unless you're checking out the fact that I was stupid enough to add an HTA and if you download it you get this experience you get this huge nice little one window pop up it has this little icon in the corner and that's basically the only fancy thing about it it has a flash audio player because if we fall back from the web audio player we load a flash player and so you have the full experience again just because it's fun but it's stupid the whole point that I'm making is that tech that PWA is like Jake mentioned are only been kind of a collective the collective concept of a PWA is new when Francis Bearman came up with it only a year ago back in like June of last year but the tools behind it the things the fundamental pieces of PWAs have existed for a very very long time this offline application is not a new concept there's a lot of pieces of the web and a lot of pieces of PWAs that aren't new concepts they're just finally good versions of concepts that we've tried to do multiple times and there's a lot of things that you can do today to kind of implement that one of the things I hear regularly from people is that they're really excited about PWAs but they can't ship them today because they can't wait to do a full site architecture they can't wait to implement all these different features and that's just not true you don't have to wait to do this stuff you can start implementing pieces today for example sorry I forgot my thought leader it's not a radical new way to create websites it can also be a radical new way to update websites you can do stuff today on your website that already exists for example the web app manifest in case you haven't ever seen it the spec it's a very simple document all it is is a JSON object that exists as a file on your page you have stuff like your language attribute the text direction the name of your document the description of stuff so it can show up in like application manager page an array of icons so that you can just support a bunch of different devices even stuff like orientation you can finally lock your screen to landscape or you can do stuff like a theme color so you could affect say the title bar and then you can go on on windows we're looking into what we can do with that you can even actually specify related applications if for some reason your company thinks a native application is better but they're still cool enough to do a pwa you can say if the user has this native application installed fall back to it if they also have that and you can toggle that with the preferred related application flag it's super super simple to do this and the great thing about it is there's no javascript API to this concept you have that one jason document you add it to your page and you are on your way to having a pwa you just inject it in there and you might be noticing actually sorry one of the cool things I wanted to actually talk about was that we are really really excited about pwas on edge and the one thing that the bing team is actually going to be doing is crawling the web to look for these sites that have web manifests and when they do we believe we're going to actually be ingesting them into the windows store automatically for you and so you can easily opt out of this if you don't want to have it as a part of it but what will happen is you automatically get interested into millions and millions of windows users you have this ability to reach out to them and once you're involved in our windows store automatically, just by shipping this web manifest you can start doing feature detections for the windows winRT APIs that basically should pretty much any windows API that you have access to you have full access to in javascript we started doing this work in windows 8 and it's available there so you can do stuff like integrate with the system calendar just by doing a simple feature detection script and then checking to see if you're in windows and if it is show the full calendar you can integrate with Cortana you can integrate with a lot of low level things and have a truly native application feel in website code that you ship out automatically just by adding a manifest it's a really cool thing to check out and to make it even simpler you know so I was sitting and thinking about how a lot of this information was you have that JSON object and a lot of that information that's on that JSON object is already in your application and all these meta tags that we've had show up into this tag soup at the top of our page for a long time now and so I created this node application sorry a node plugin module thing called manifestation it takes a URL and then gives a callback to you that just generates the most fully featured web manifest object it can create and then it's featured like for example our language detection it loads up the whole page using Cheerio just like a server side jQuery and CLD the compact language detection which is a binary object it's very similar to like how Google translate works it can actually look at the context of words and how they're used until a difference between Portuguese and Spanish or something like that and so we go ahead and load up the HTML of your page we go and check for the language attribute if that doesn't exist we go and check because you might be making an HTA into a PWA for some reason then after that check the DC language attribute Dublin core if we have any librarians in the house it's like a super A it's a really old meta tag that no one uses but if it does exist we want to use it in there and then after that we'll fall back to CLD where we'll actually look at every single word on your page parses HTML and try to automatically detect what the document is just like you do if you open up Chrome it's foreign language it's like hey do you want to translate this from Portuguese it's exactly the same type of concept and so after all that we send back the string of what that language might be that's just one of the detections that we do there's for every single field on web manifest we have one this is the beginning the top of like a 200 line file for images where we go and scrape every single image that's declared as an icon we download it check the size ensure that the mime type is correct ensure that the extension is correct and do all this stuff and generate the full icon array for you automatically in fact it's so easy to do this I made a website so that all y'all can do it like literally right now you can go to web manifest this website it exists it's this cool domain it's super simple again I love stupid domains you just go there and you put in the url hit submit and it will download your web manifest file that will automatically be generated from the code on your site already you don't have to do anything you just download this you add it as that link tag and it works it's great and you're the beginning of having a pwa and you can be ingested in the Bing store soon you just get this pop-up download you got it, it's awesome so it's web manifest it's a super simple thing if you want to end up changing what I do because we try to be fully featured you might want to remove some of that stuff if you think it's unnecessary I added a short url to the validator you can just go there you paste in your JSON object that you modified and it'll tell you whether or not it's valid if you have an invalid manifest file it actually won't count as a manifest at all so it won't work you would be blocked from doing a pwa you want to make sure you have a valid piece of JSON object also the spec on this is really pretty simple if you've ever been interested in doing w3c work if you've ever been interested in getting more involved this is a great one to dive into we're all super friendly we'd love to get more feedback on this stuff and if you guys have stuff you want to be involved in it's a great one to check out it's a really fun thing to work on so while we're talking about what we can do today you don't have to wait for all these new features to come Jake just blew our collective minds with the stuff that's coming in the future and there's a lot of really fun stuff but there's also stuff that you can do for a long time on the web that is amazing take for example web workers they actually landed in web kit back in 2008 and 2008 in web years is just geologically the chrome icon here is wrong it actually was that back in 2008 it was a long time ago and a lot of things have changed IE 8 wasn't even released yet it was a long time ago but since it's been around for so long it's phenomenally supported it's supported pretty much everywhere it's back to IE 10 it's really really cool and if you're not familiar with web workers it's a really simple API has anybody here ever implemented a scroll handler like on scroll, don't lie we're among friends you can rank up your whole page and that's because everything on a browser is completely single threaded because the browser doesn't know are you going to modify everything in the DOM in that scroll handler so it can't relay out stuff until your scroll handler is finished because it would be wasting work it sucks because most of the time you're probably not but it can't trust you and so what a web worker does is it gives us the concept of having a background thread you're able to say like it gives you a new JavaScript context that you send strings or possibly objects to depending on the version of web workers you're working with and it's like hey, go calculate this and then send back the results and it can do that completely in the background so it can do some really hardcore heavy number crunching without any way affecting your scroll performance you can do a lot of really cool stuff with it take for example Pokedex.org I'm sure a lot of us saw this it's Nolan Lawson, one of my amazing co-workers created this website as a really advanced PWA it has an incredible performance on the site and part of the things that makes it so fast is because it's like a react-ish powered thing, it's using virtual DOM and it actually calculates the virtual DOM differences inside of a web worker and then sends back the diffs in between so it's able to render stuff faster something the React team is actually investigating currently is doing virtual DOM diffing inside of a web worker it uses like I said virtual DOM it has this concept where it gets the diff, it sends it over to the UI thread where it applies all that stuff this looks important, I included it because it looks sciency but the cool thing is you have this phone, this is a Nexus S which is a 5 or 6 year old phone, I should know this I'm at a Google conference, I'm sorry but you get incredible performance this is like he just did this last year and it's phenomenally fast and look at how smooth that animation is and one of the things that he credits as being able to do this so well is by doing his DOM diffing inside of a web worker there's tons of crazy cool stuff you can do in web workers take for example Modernizer like I said I'm the maintainer we have our website our dynamic builder is completely client side I built in a whole lot of stupid stuff into it like I showed you the HTA right now and all these different things are check boxes and every single time you check one of those off it'll go ahead and download the entire module they're all modular pieces right and one of the problems we had on the Modernizer team is that people were including the entire build of Modernizer and as we grow to more than almost 300 modules that can be a gigantic piece of JavaScript and frankly most of you don't need to know whether or not border radius is supported in the browser right all these tests and all this code that isn't running that we didn't want to include and so to make people aware of what they're doing when they start checking out features we actually have a gzip calculator up in the corner and so as you check stuff off it updates and we do that full gzip comparison inside of a web worker in the browser without ever going to the server we're able to do that and we're able to do that every single time you click off stuff because web workers are so cool in no way does it affect your scrolling your performance the animations or anything else it's just a really silky smooth fast experience and you're able to get some really neat information in fact I love web workers I like to push them as much as I can so much so that I'm looking into a new project right now that I've been working on where it has a terrible name if anybody has a better idea I call it web worker preprocessors we all use transpilers we've all used stuff like Hamel or Jade or other stuff like that I love them I want to take them and run them on this client side I love sites like JSbin or CodePen but I want them to be a PWA I want to be able to run that offline and so what this is doing is actually a tool chain that automatically creates cross-compiled version it transpiles transpilers to run inside of web workers I have a number of ones already working including some Ruby based ones less support, slim support Pug, Jade, the old version of Pug we have Auto Prefixer and even Hamel and I'm currently working on SAS and they work the Ruby stuff is actually transpiled using a cool project called Opal which takes Ruby code and transpiles it into JavaScript and they work I have every single version of slim a similar to Hamel Ruby version throughout its get range like literally 58 versions of it running inside of a web worker passing their own full test suite and it works really well if you're interested I'd love to talk about it because this is what I've been doing at night web workers are cool you can do a lot of crazy cool stuff cross-compile Ruby into JavaScript in order to compile your template it's complicated but I think you all know what I'm talking about the whole point of what I'm saying with all this nonsense and stupid ideas is that when you build stuff try out something stupid like there's a lot we can do all kinds of really crazy cool stuff on the web and you shouldn't be thinking that you have to wait for it to be supported everywhere to do something stupid try something cool today in one browser if a feature is supported in one place be it Safari, be it Edge, be it Chrome be it Firefox, try it out feature detect, do it and ship a feature the way that browsers actually decide on whether or not to support a feature are based on what y'all do if everyone started using web components back when they first were introduced then everybody would be supported on web components it's this weird prisoner dilemma where people think they have to wait for browsers but browsers wait for the people start using stuff that interests you give the developers feedback and make really cool stuff and so you don't need to wait for a rearchitecture in order to start shipping a PWA you can start shipping individual pieces like the web manifest like a really simple caching service worker do it today literally right now almost every single site that can implement that stupid 18 line service worker that I had in a way and you will instantly your whole site might not work offline but you can have faster caching you can have a faster load from almost all your users try out the new signing features and try it out today try something stupid the web is really cool thanks everybody were you going to go off that way? no that doesn't work I've been around forever and ever that's awkward right so what do we know it's a break and breakouts and codelabs yes and you've heard loads from us in the last sort of day and a half two days and this is a conversation it's a two way street so this is your opportunity to have conversations give us feedback on various topics and there is quite a lot going on yes so in the main auditorium which is here from 4 to 430 from 0 to service worker never heard of service worker 430 to 5 scalable loading which is kind of h2 push that sort of thing floor 1 it is ground floor yes because I would have sent you up there if I was in the UK but I'm not so it's down here 4 to 430 is web assembly and firebase as well so there's two out there and then at 430 to 5 it's push notifications and background and web VR so England is 0 based on floor numbers I've got the right thing isn't it I've got to be honest with you I'm happy about that so floor 2 from 4 to 430 it's Ampers starting point at the same time media techniques and approaches 430 to 5 it's Houdini which is all the kind of magic pool css what if you can write your own layout engine things like that it would be amazing and then 430 to 5 the web platform predictability pain points and stuff out there as well and in here so just make yourselves go and get yourselves a drink or whatever and we'll see you back here at 5 o'clock for the browser panel don't forget to submit your questions I've got to pop this here for all the incoming things oh I think a lot of people are still out in the breakouts well your snooze you lose they're going to miss out on the next couple of rounds of the quiz awkward that means you can go ahead huh there's terrible phones up for grabs and let's me forget the mugs oh yes the mugs of course all right shall we go for a question yeah we shall yeah I'll read this one for well that screens so you probably have the question on your screens now but this screen is frozen so let's there we go there it is we don't have sound though maybe nice we had sound could we have sound we'd love it there we go look at the display of subsequent elements while the resource loads sure we did this are you sure you just feel like we did this oh there we got this we've got an image element there we have a link rail style sheet async a script element well so we've got a kind of high confidence one of them there not so sure is that our highest that we've had I think so yeah I mean people are really confident on that 90 percenter we were saying oh people are pretty confident scripts going to block not so sure about the the link rail style sheet thing there let's see if we can get up the actual answers interesting so async attribute on a link element it's a red herring doesn't do anything it only works on our HTML imports if you are going to async load some style sheets you've got to go via javascript really well yeah I think chrome and firefox if you create the element of javascript and append it it'll be async safari will still block recent changing chrome there's some interesting facts okay you're going to read this question right what is the result of the following code is it a reference error does it log true log false or throws a syntax error we'll say it's not a parse error it's got those magic quotes that's a copy and paste error that is exactly it's almost like we had a document with these it almost like it did that so we've got some confidence in one of the answers one of them is more than the others they're very steady there all hovering around oh it's dipping there's a change I feel like we need to settle a little bit before we call it one question I have to ask why event source keeps us falling asleep that's the reason we had to refresh the machine very exciting do you want to look at it yeah let's look at it reference error is the most popular answer logs false logs true syntax error take reveal the answer the answer is it logs true and the reason it logs true is when you define the key of undefined the property it goes oh I'll turn that into a string for you yeah but it's just weird it seems to be the weirdness of javascript why do we even do this job I don't know all the same so then when you ask for is the string of undefined in the object it says yes it is so what's happening now then oh it's the browser vendor panel and I in fact will be needing this bit won't I yes I need to know who it is in fact that is joining me on stage you talk for a second Jake is everyone having a good time we're moving forward to burning this suit I mean maybe even with me still in it I don't mind oh hello Alex this one's Alex Russell my first guest Alex Russell you keep going and we have Jacob Rossi from Microsoft we have Harold Kirschner from are you coming the reward from Mozilla Andreas Bobins from opera keep going keep walking Oslo Maslow Gombosh from Samsung hello and Alex Russell I've already done Tal Oppenheimer there we go well this was well rehearsed wasn't it is it do I go away now yeah don't kick me around big round of applause for the panel though now you know that nightmare feeling where somebody invites you to fancy dress party and then hours before they let everybody know that it's no longer a fancy dress party and yet you show up in your fancy dress I don't feel like an idiot not one bit now the other thing that has occurred to me is that live questions are actually quite a lot of fun and I thought well I have mugs and they could act as an incentive so there are microphones there and I think maybe over there so if you have a question for our panel please do feel free to avail yourself of the microphone and afterwards you get to come and pick up a big web quiz mug that is exciting we'll get on with our first question t