 I'm Samantha. I'm here to talk about progressive web apps and how to do them with Ember today. I work at YWorks with these awesome people. Oh, OK. We basically work with Rails and Ember right now, and we come from Uruguay. Homer is pointing there. Where'd you find it? So to start, let's see what a progressive web app is. What's the definition? In Adios Manis words, a progressive web app takes advantage of new technologies to bring the best of mobile sites and native app to users. They are reliable, fast, and engaging, and they originate from a secure origin and lower regardless of network state. Why should we care? Someone may be asking. So I have a dream. This year I was vacationing in New York, and I just wanted to know the train times. So I Google just as everyone does, and I got this screen. I'm fairly sure most people have seen this screen at some point. And I don't actually want to download every app. Like in some cases, I'm just going to be using the web for a couple of days, or maybe just once. And it's not the only case. Like here, I can use this app so this is not so bad, but it's still asking me to download something, even though the web is totally usable from a mobile device. If you were here at last EmberConf, Tom and Jehuda actually talked about this and what the Ember community was going to be doing to improve the mobile web and what we can do to use this. And that screen that I don't want to see anymore is not the only reason we should care about improving web on mobile devices. Most of the traffic nowadays come from cell phones. So like almost 70% comes from a mobile device. So making our Ember apps work better, I think it's a safe bet here. Okay, so going back to what a progressive web app is and how we can make one, one of the first points is that our app has to look good on a device. I mean, this is fairly straightforward. I think nowadays most web do look good. They are responsive. If you try to find an example of a site that is not very good at mobile, it's actually hard to find it. But we can do some small things to improve this. The second point would be that our app could be installed on the device. One of the differences between the web and native apps is native apps are accessible through the home screen. We can also achieve this with a web app. The work offline. I think this is one of the biggest differences. Native apps, even if they don't completely work when you don't have connection, at least they show something. They load and they show a better error than what we get on the web. But we also have ways to achieve this with a web app. And the big point, the performance, as we were talking about, still some people prefer native because they work faster than web. So let's start with the looks. Here I have native Trello and web Trello. I'm going to be using this as an example and I have my progressive Trello client. You can check the code later at GitHub. If you look at both, they do look fairly well on the device. There's not such a big difference. There is basically a style difference, but you can get both looks with HTML and CSS. That's not so hard. So the main difference here is an app bar. So that's the only thing saying that one on the right is not a native app. But we can change this. We're going to be seeing this in a minute also how we can make our app install on the device or get a similar experience to an install. For this, we are going to use the app manifest. So the app manifest is basically a JSON file with a set of configurations. For instance, we can tell the name of our app, the description, the theme color, the background color, and the icons. And the browser is going to take this information to make the experience better for native users. So here I have my app before the app manifest. If I save it to the home screen, I just get a generic icon that doesn't say much. And after I load the app again, I still get the Chrome on the browser. So you know it's not an app. After I add the manifest, I already see some change on an app bar. I get the icon that I want. I get the name that I want. Again, I get a splash screen. So it's getting better already. And I lose the app bar. So at this point, this looks like a native app. There's not such a big difference. And this didn't take much effort, except that only Chrome supports the app manifest. Yeah. Well, it's not so bad. Don't despair. We do have ways to get the same result on iOS. You just need to add some made attacks to your HTML. You also give the icons the name, the color. Here is my app on iOS. So the icon, they get by default without these tags. It's better than Android. At least they show an image on my app. And I still see the browser here. After I add the made attacks, I get the icon that I want. I get the name that I want. And after I load it again, I lose the app bar. So we get a similar experience as with the app manifest, which is need to add more information. This is how you can do it on Windows, if anyone needs to support it. Also, some made attacks and a configuration file. Basically, the information is the same in every case. The icons, the colors, the name. But since we are doing Ember here, you don't have to write every file. We have an item for this. With Ember web app, you install the item and add a configuration file. I'm going to show you there. It's similar to the app manifest. But the item by itself generates the JSON file, the made attacks. So you don't have to support every case the item does it for yourself. This is how I imagine it would work if the app manifest was supported by every browser. You just need one config file. So up to here, we've seen a small change that we can make to our apps and make them look more native and make the install experience better. So we can have the icon that I want on the home screen. But we need to see how to make our app work offline or behave better. So first, that's our app work offline. Here, I'm enabling the airplane mode. I have my app saved on the screen. I see the splash screen, and then I see the dinosaur. So we know this is Chrome. For this, we're going to use the service worker. How many people here have used or heard of a service worker? OK, yeah, I figured. So this is not so new. So for the ones that don't, a service worker is basically a script. It runs on the background. You declare it on your page, and it gets downloaded with your page, and it stalls on the browser. And it runs on the background, so it doesn't block your UI thread, and it allows you to do stuff, even if you're actually doing something else on the screen. It doesn't need your web page to be open. The browser can run it, even if your site is closed. And it doesn't need the user to actually do something. You can do a lot of actions. Here, we have the lifecycle of a service worker. What happens after it's downloaded by the browser? There's a few events that we actually care more here. The first is the install event. This is after your service worker is downloaded. Here, you can, for instance, download your app assets. We're going to see it later. After the install event, if everything works, you get your service worker activated. Here, you know your service worker is running. And I think this is the one that we care most. Basically, your service worker is going to act as a proxy. So for every request that your site makes, it's going to go through the service worker. And it gives you the flexibility to actually decide what to do with that request if you actually wanted to go to the server or not. So one thing we could do, as I said, is save all the assets of your app on the install event so I can download all the HTML, the CSS, the images that I need, and save it on my device. And I will have it from now on. So even if I'm offline, I can still show that. It would be something similar to downloading your native app so we can get a similar result. As I said, also, it intercepts every request. So here, we can, for instance, cache all the responses for every request our site is making. We also can check if the network is available or not and return something from the cache or return any default response or go straight to the network. It gives us a lot of flexibility to make our app work offline. Background thinking. Since it runs on the background and doesn't require your app to be open, you can do some stuff even after the user closed the website. One of the things is bringing more data. If you have a news app, for instance, you can download the latest news and then notify the user because we also have access to push notifications here. So we can get the latest info to show a push notification just like a native app does. And a lot more stuff. The people that is developing service workers also adding more support for the other APIs that is going to give us a lot of power to be able to do stuff from the web that we could only do native before. And yes, we have items for it. So you don't have to write the code for your service worker. I mean, you could, but you don't have to. And this is a good start. Both items achieve the same result. They just take a different approach. So you can pick the one you like more. Ember service worker takes unapplegable approach. So the basic item just registers your service worker and coordinates all the items that you add on top. So for instance, up to this point, I just have a service worker, but I don't have my app working offline. If I add worker index and asset cache, I have all the assets from my app cached when the service worker is installed. So after I access my app once, I already have this saved. And if I am offline, I can at least show the HTML and the CSS. But you still need to handle on the case for the rest of the request like the content. And we also have an item for that. There's a lot of items actually that you can pick, but this one is the basic one for me. Basically what it does is if the network call fails, it returns what you have on the cache. And it also caches what comes from the network. So after a user has accessed your site once, he will be able to at least see what he already saw the last time. They promise that you can have enough line for a step in 30 minutes and it's true. The other item, you can also do the same thing. It takes a different approach. You can need to give a configuration file. So by default, just by installing the item, you have your assets cached. If you add here your configuration, you can name all URLs that you want to have cached on the install. So they are going to be available always. Also what happens when a network call fails, you can have some asset that is going to be returned always by default. And you can also name all URLs that you want to go to the server first. And then if that fails, you can return something from the cache. There are other alternatives also, but these are basic ones. So here's my app before the service worker. We remember this. Here's my app after the service worker. So I don't have a connection, but I'm still seeing the same that I saw on the last first day I opened my app. So the app is working offline. That's it. Yeah, but it can be that easy, can it? So nowadays only Chrome, Firefox, Opera, and Samsung support service workers. Edge has it in development, but Safari doesn't. And we don't know if they will and when they will. So we need another solution for this. If you're thinking of not supporting iOS users, they do represent like 22% of users worldwide. And in the US, they are the majority. So we can't just leave all these people hanging. So let's enter the application cache. I think everyone or most people have heard of it. So it's the old and not so fun, brother, let's say. But it just work on every browser. So it's the safe bet if you want to have your app working offline. So for those that don't know the application cache, you basically declare a manifest file and you name all the requests and assets that you want to have cached. So after you access it once, it's going to be on your device saved. You also have to name all the requests and assets that you want to go straight to the network. So the difference between application cache service worker is the service worker is way more flexible since it allows us to decide what to do on each request. Application cache, you just have or the cache or the network. You can do both. And yes, we have an add-on. The broccoli manifest add-on, what it does, you install it and by default it will generate a manifest that it caches all your assets. So at least your HTML, CSS, images are going to be on the cache. But you can also add more functionality to it. You can say which files you don't want to have on the cache, which files are not on your assets and you do want to have on the cache. So with this, we have our app working offline on most devices. But we still need to decide what to do with users that want to create something. So for instance, in my Trello case, if I want to create a card and I don't have a connection, I can't now because the way the web works, it will actually go to the server. Well, we have solutions for this too. We can use the local storage. This is basically a key value store on the browser. It saves just strings, so it's not recommended for large states of data, it's more for preferences. But we also have web SQL and index to be and local for Ash, that was fast. So web SQL and index to be are allowed to save more data on the browser. And local for Ash is a library from Mozilla that wraps all three. So in case your browser doesn't support index to be, it will save your information to local storage. And yes, we have items for it. So as the name says, and the local storage adapter is a number of data adapter for local storage. So you just add it to your app, you choose which models are going to be saved with this adapter and the information is going to be saved on the browser. So you don't need a connection for this. Local for Ash does something similar, except it's using local for Ash instead of local storage. So up to this point, we have a way for users to create a card and save it on the device, even if there's no connection, but you need to decide what to do afterwards when the user is back online. How do you send this information to the server? With these two solutions, we need to implement that other part. With Ember Pouch on the other hand, Ember Pouch is also a number of data adapter. It uses pouch DB that is also a wrapper for index DB. The good thing is that if you have couch DB on your server, there's an OSQL database, the thinking is provided for you. So you don't need to implement everything, there's already a thinking solution in place. So up to here, we can have our app looking better without much effort. We can improve the experience when it installs on the device and we can have our app working offline. So we already improved the experience of our users a lot, but we still have to do something about the performance. So for us, let's compare how our apps behave. Here on the left, I have native Trello and I have my progressive Trello on the right. So both load kind of instantly and we see something in both cases, but native still shows my content way faster. Yeah, so we do have ways to optimize it a little bit. So the first thing we need to wonder is how does our page render fast on the first render? So before I save it on my device, since we are using Ember, the user is not going to see anything until Ember loads and actually renders your site, but there's another way to change this. So for instance, with Ember Cliff Fastwood, we can have our app render on server side and even if the user doesn't have JavaScript enabled or even if the JavaScript takes too long to download, it's going to see something because we are giving the HTML for the first screen to the device. You just have to install it. It's fairly easy, but you might have to start optimizing some other things since you are rendering HTML, you have to wonder about the CSS and the images, but it's a way to improve the first render. For the second page render, actually what we have done to this point does help because we already have our asset saved on device. It won't take that long to go back to network and download everything again, so it should boot faster the second time. And the time to interaction as, well, we have already heard, Ember is a large framework and your user is not going to be able to use the app until all the JavaScript downloads and gets parsed. So we have to figure out ways to reduce the size of the JavaScript and one way to do it is using Ember engines. So Ember engines is not only meant to reduce the size of the JavaScript for mobile devices. Basically, it allows you to compose your app into smaller parts. And with lazy loading, you can ensure that your user doesn't download the whole JavaScript. It downloads just what is accessing at the time. And once you navigate to another route, it will download the JS for that route if it's in another app. So with this, we can make sure that our app, if it's too large, it gets cut in smaller pieces and the JavaScript size is going to be reduced. We do have some tools to help us in developing progressive web apps. And one that is very good is Lighthouse. This is a Chrome extension. Here is how it works. You give it your page and it will do a set of tests and give your report. So this is the report I got before I added any of the solutions that I just mentioned before having the manifest, before having the service worker. So my app is not very progressive. Basically, it doesn't work offline. It loads too slow. There's more information, but it also doesn't give you an icon when you save it to the home screen. After I add the web app manifest and the service worker and the app cache, if I run Lighthouse again, I already see some improvement here. So my app works offline and you can save it on the device and it gives you an icon, but you see the big red there that says page load is not fast enough. And I said that we could improve this with fastboot, so let's check if we actually do see some improvement here. And yes, we do. We went from a service 77 to a 90. So the first meaningful paint gets green now. It's faster because we are giving HTML, but we still have a time to interactive that is not so green. Let's see what happened with engines. The bad news, at least my experience trying it, is that engines with lazy loading and fastboots don't work together right now. So the advantage of adding engines for this case that was the lazy loading cannot be used here. Up to this point, I mean, people are working on it. So here's what happens if I just have engines with lazy loading, but I don't have fastboot. So even though I still get a good experience, the first meaningful paint is not so good. So in this case, it might be better to just have fastboot. So going back to the initial realm of not seeing some library site, ask me to download their app. I think it's possible to improve the experience of mobile users. I'm not saying that we shouldn't do any app. I'm just saying that we don't need to do an app for everything. And even if you have an app, you still can improve your experience. Like the first, add-ons are fairly easy to add and they give a better experience for the web. It's possible to do it with Ember today. We do have some solutions and the people who's working on improving them. And it can't get better. So as I was saying, fastboot and engines still need some work together. And there's also a lot of stuff that we can do to improve this and as I showed, most of the job here has been done by the community. So anyone can help, even if it's just using these technologies so we make sure all browsers feel like they have to support it. So we need your help for this. Thank you.