 Okay. I've been working with Ember for a while. I'm talking about my experience building web apps with Ember. My name is Miguel Canba. I'm from Spain, obviously. You can reach me in any of these places. And I have, I am entitled to speak here, because I know how to pronounce Ember any way. I've been working with Ruby and Ember for a while, but like most of you I imagine mostly in desktop. And the thing is my most complex project in Ember probably is this one. It's an online video game in Ember. It's a fantasy manager, a football fantasy manager. And there is a few interesting facts about this game. It's a very big project. It has been two years in development. It's began in Ember 2.0 Beta 6, something like that. So it has been a long way. It's almost up to date, I think. It's not in HTML files, but it should be soon, very soon. It has a very complex UI, like an action house. You can see the match in real time with the ball moving around. It's quite complex. And we also have a huge amount of users. I think now it's six million. And we have a web Ember client and native apps, iOS, and Android. And at the time we tried to see, okay, let's see if we can build this. I mean, the mobile, the desktop was the first thing we did. And we tried to say, okay, let's move this to the mobile and see if it works. That was in Ember 1.5, I think. We made some tests. But the main market of this is Europe, Southern Europe, Spain. And I think a very big market is South America. And you can expect people in South America have the latest devices. I mean, iPhone 6 Plus and everything. So performance was very critical. And we decided to go native for all. And I think it's a good thing. But I learned a lot of things there. And the most important one is if you want to make money, and it's why we are here. Not here, but in the profession. And we wake up every morning and go to the office and everything. It's that we need to think in mobile first. I mean, it's something that you heard very often. But it's very true. I mean, these are some numbers. The last time I checked, there was around four million players that registered in the game using the desktop client. And 500,000 players using the iPhone app, not even the Android. The Android was not released at this time. This took two years and this took two weeks. You can see that there is a huge difference in users. And this is in a market, Spain and South America, where 93% of the devices are Android. And this is the iPhone app. So it made the numbers. It's very important to be on mobile. There is the Android. I mean, this is where the money is. But I have some numbers to share. I mean, this is from our search of the GSMA, the mobile consortium that builds networks and everything. These are the numbers of the internet a year and a half ago. There is around two millions, two billions of users, American billions of users with landlines in the world. And pretty much the same number of users with mobile connections. But in five years from now, there will be around twice as much users in mobile than in desktop. And this is very important. These are us now, us in five years. This is the third world and the second world, South America, Africa, South Asia, et cetera, now and in five years. We are about to grow at 15% and it will double the size in five years. So in advance, on top of this, we have to think that there is a lot of devices in five years that are pretty inexistent right now, connected cars. There is already a bunch of smart TVs, but you won't find a smart TV in five years from now. Every smart TV will be a smart TV. And the internet of things, which we don't even know what it is, but will be something. So there's a very important thing about being native or going to the web, because if you go native, you need to choose one path of the other, or both, or three of them, if you include Windows and Linux and everything. The web is the only platform that will be in every device, you can imagine. It will be in cars, it will be in phones, it will be in everything. That's a huge selling point for doing things in HTML. So right now, where are we treating a good mobile experience like a nice-to-have, like something, okay, it's nice that this scale is very well, it's responsive, but right now we develop thinking in the machine we are developing this in this laptop. But my products will more likely be used not in my laptop, rather on my phone. I carry my phone all the day, but not my laptop. Having a good mobile experience is core for your business. When I came to London six months ago, now I am a freelancer, but I started working on this company, that business, it's literally a name. And it's a company that makes native apps. I do the Ruby and I do the backend of many apps. And I learned something there. UX is very important. Product owners used to care about the thing they sell. I mean, this app needs to show the news or receive push notifications. But people, for example, from Google, for the Chrome team, they made a survey and they discovered, they ask users of news apps which feature they like the most about using an app and not a web page. And they thought that the response would be, we have offline news and we have push notifications of important news. And the answer was, no, what we like is that the UX is very smooth. And people care about these details. So as developers right now, we are kind of in the middle ground between designers and coders. I mean, people doing our job, for example, people that work in Ember. We need to care about the sign. We should aim to be in the middle. This is where I am. So what makes an app appealing to a user? Appealing means at the end sales. I mean, you want to sell what you do. Basically, there is three pain points in mobile apps that we need to fix and we can fix right now. One of them is we want our apps to load fast, initial load, respond fast, and work offline kind of. It's not everything can be done offline, of course, because we need communication, but it should at least not break completely. I'm not going to talk mostly about the last two points, but about how fast there is a few things like us as a community can do right now. There's a few interesting things coming. The first one is specific to Ember, it's Ember fast boot. I mean, when we load a single page application, we first of all load the HTML, then we discover the assets, like the JavaScript and the CSS. We request them, we get them, and afterwards we boot our app and probably make another request to the backend to load the initial payload. I mean, something maybe our user or the news or whatever. Ember fast boot pretends, this intention is to make everything in one request. So we query our server and there is an Ember app running on the server. It renders the HTML, sends the HTML and the assets and everything, and as soon as we have the HTML, we can display something. We can show the app to the user. Even if Ember is still loading things in the background. In fact, they are even making experiments to kind of serialize the initial payload within the HTML because you can basically serialize the entire store and then pretty much dump everything into the store and you're ready to go. This will make our application much faster. Another thing people is working is removing jQuery as a dependency. We want HTML to be lightweight and it's not. So the first step is basically remove things that are not mandatory and make it optional. JQuery should be one of them. Another is tree shaking will be much easier when ES6 models are kind of finished and established. The idea is if you have an app that only uses part of Ember, why do you load all Ember? Things like maybe sets. Maybe you are not using sets. In fact, I think they are deprecated now. I don't know. So the idea is if you can know in advance, given the models you load, which part of Ember, what part of Ember are you using, you can just make a custom build with only the things you need. And these two are just general for any web application. HTTP2 will make things much faster because you can make server-push content. So when you request HTML, your server can know, okay, this guy is requesting the HTML. And every single person that asked me the request the HTML, they also want the CSS and JavaScript. So take it. I know you will need this. And browser catching. So why do I need to download the entire app each time I enter? If you go to the store and buy an app, you don't load the app and you have the app forever. With a web page, basically each time you want to use it, you don't load the entire thing. So if we can cast this thing, you only need to make a request once in a month maybe, depending on how often you deploy. This is an interesting one. Response fast. We want, as I said, very smart, very smooth UIs. And a fast UI is how much time there is between when the user makes an interaction and when the user gets the feedback. When we use the input, when we are talking about mobile, we are typically talking about fingers, I mean, touching things. It happens that we still think in clicks and drags, and it's not the case in mobile. We have another event. So please, right now, since this very moment, please stop using this. Have something like this. Use the touch start, touch move, and touch events. It's kind of the most down mouse up, but they are native. And you prevent the default. So if you are on a device that has this kind of events, these events will fire, and this won't because it's prevented. So you will have the immediate response of a touch start, immediate response of a touch start event. And if this is reused between mobile and desktop, you still have this. So you can have the instant speed of touch events without having to mimic the click, which is a hack. Browsers implemented this fallback from touch events to click because at the beginning there was no web pages prepared to this. I mean, you need to, okay, someone taps here, and if nothing is listening for this tap, means, okay, it's a click, and it works. But clicks are atomic. They are not native. In fact, in iOS, by example, they have a 300 milliseconds delay. And touch events, on the other hand, you have fine-grained control because you know when the touch begins, the touch ends like with mouse down and mouse up. They are native, which means these are the actual events the browser fires. And the click is something emulated, let's say. And it's instantaneous. I mean, if I listen for the tap-start, tap-start fires immediately. And extra, you can have multi-touch. There is not something that people using two mouse to make things. And the other part is how do we update the app? There is this graph I take from a presentation of the Chrome Dev Summit. People, users receive the perceives things as blazing fast, instantaneous, when it's below 100 milliseconds, more or less. When you have something between 100 and 300, it's pretty fast. This is where people start to, okay, this is uncomfortably slow. And when you surpass the one second, people actually start to make questions. Did I click this button? The app is frozen. People doubts about, okay, maybe I did something wrong. So this is the pattern we usually follow when we develop apps. We make some kind of gesture recognition. So we detect a swipe. And then we fire a transition. So we fetch the data, wait for the data, and then we display the new route. Something like this. And I have a few videos. Let me put it on... No, this one. Speed, a quarter, play. I make a swipe. I want to lift the finger. I did the swipe. I command to make a transition. And I transition. Let's put it in. I made a sweep, lift the finger, and then it's when things happen. But there is nothing here. It might even seem like an accident. I'm here, and suddenly I'm in another article. I don't know why. Because when you think about UX, animations are in fact something that are not just... because it's pretty. It helps to build mental models. I have a very... When I think about good UI, I always think about material design in Google. I mean, you don't need to follow the rules of material design or the patterns or have these guidelines. But as a general guideline of who to build a good UX, this is quite a good resource. This is an animation. You click something and things fade in or come in from the side. And this is the same thing. Just like popping or appearing from nothing. In actual things, maybe apart from lightings, nothing happens in a fraction of a second. When something appears, it appears from somewhere. There is animation. This helps the user to understand what they are supposed to do. I have another video here. I'm sorry if I haven't shown any code yet. There will be some demos. This is the same thing, the same app. But in this situation, I have the animation. I made the gesture at some point. I made a swipe. And the things come here. This is not displaying the content any faster. But if a user makes a swipe to the left and goes to the next news, the next article, he knows already that if he makes the opposite move, he will go back to the previous article. So this is why using animations wisely can help you to build a good user experience. But there is a point where this is not fast enough and we want people to have instant feedback. So if you can't make a network request go faster because there is latency and you can deal with it, you need to make things look faster. So a way to make things look faster is... No, I'm sorry. This is, again, from this very good talk by Paul Lewis on the Dev Summit. When a user makes an interaction with a screen, there is a few moments. The first 100 milliseconds, the user doesn't perceive that his action has ended. Which means you can make work here and at the end, when the animation ends, there is a few milliseconds where the user realizes that the animation has ended and he can continue working. So taking advantage of this, we can make things happen in parallel. So if instead of gesture recognition, we make gesture tracking, so instead of waiting to the gesture to end and know that this is a swipe, I can recognize that the gesture is going to be a swipe because it looks like a swipe. Eventually, he will lift the finger. So why wait? If a user makes a swipe, let's fetch the data and update the view even if I don't have the data to fill the view. And afterwards, make the transition. So the same slow speed. When you move... No, this is a false move. Now, you have the card coming in. You have the... You can... I mean, the user knows that the application is responding even if I don't have still the next article recovered from the server. So the user... When the user sees this, he knows even if the information is still not available, he knows that the application is working. If a user has instant feedback, he knows that everything is going okay. And it makes two happy users. So that's why it's important to make things happen as fast as possible and delay maybe updating information to the point you can, but you already have shown the user that everything is working. And if you do this, it's very easy to say, okay, I have the pieces when the network is bad, this is the work, but when the network is fast, when the network is smarter than the network, I can preface the content. I have the best experience possible. People don't need to wait. I mean, they see everything coming. And this is a mobile webpage. I mean, there is a lot of reasons to use native apps, but there is a lot of reasons why web apps can be better from some kind of applications. So if we want animations to help us to improve the sense of speed in an app, they have to be smooth. That's when the frame rate crumbles. That's when they defeat the purpose. But JavaScript animation are quite hard. I mean, it's because to control everything involves using request animation, frame, makes the maths and everything. It can be challenging or at least cumbersome. So there is a new API coming to the web called Web Animations API. It's what you wanted all your life, but you weren't aware. It's like the Bastard Kit between CSS animation and JavaScript animation. But it has the best of both parents. It's a new standard. It's declarative like CSS, which means it's very easy to use and gives you full control of what you are doing because you can control from JavaScript what's happening. It also has nice features like CSS animation. It doesn't use the main thread. It can't even run on the GPU. So it means it's very performant when there is native support for them. And it gives you some nice features that you have to do yourself with JavaScript. You have free synchronization. There is even some things it wasn't even possible previously like motion paths, which I define a polyline in SVG, like a mountain, and I want this object to follow this like if it were some rails and a train. So this wall moves following this strange path and it works. This is a small... Maybe it's a bit small. There. This is the basic syntax. Its element is a DOM element. So you can define a few keyframes. That's the origin. That's the ending. And a time. And you fire an animation. The animation runs. And it has the same effect that having this CSS on a class, this CSS on another class, and add this class to the element. It just moves things around. You can specify animations, things like delay, the easy and iterations. And it works like if it were a CSS animation. But the key point is that when you call this, it returns a player. And with this player, you can post animation, resume the animation, play the animation backwards, change the speed, seek a given point of the time. You can do pretty much everything you want with this. So it means that you can control a CSS animation from JavaScript. There is a very good polyfill from the Polymer project. You can use it right now. That means you can use this on iOS, for example, that it's not supported right now. It's only supported in Chrome. And it's coming to Firefox. You can use this polyfill. It's not as performant this polyfill as, for example, GESAP or Green Sox or maybe Velocity. But when the support is native, it's blazing fast. I have a small demo here. This is the code for making the animation with request animation frame, the most efficient way, and with animations API. I have this diff, it's a red diff, and two buttons to trigger the animation. This is my code for the web animation thing. Yes, sorry. And then there, enough. Okay, this is the code for the web animations API. You define the keyframes, the options, and when I click the right button here, I just call animate with the keyframes and the options. That's everything I do. And this is the code using request animation frame where I request, this is my starting point, my ending point. And I call this function recursively to date things. And this is for a linear animation, not even easy and anything more fancy. You can see that this is with request animation frame. It works. It's just moving and scaling. This is with web animation API. It's equally smooth because it's a very simple transition. But let's see something very interesting. Let's go full screen with this. Okay, I have this here. And everybody's familiar with the timeline? Okay, if you want to develop for mobile, you have this open all the day. You need to measure things. This is, oops, this is, I have this here, this button. $0.click. I'm calling this from JavaScript to make it easier. And timeline, I record, I click this, I see animation, and I stop. These are my frames. It's very smooth. You see that it's almost in this. Here, this is the amount of time I'm consuming from my budget. This is the 60 frames per second boundary. So that means this animation is very fast. I'm not hitting any kind of bottleneck. It will be around very smooth with JavaScript even. Let's do the same with this other thing. Expect element. I do this. I'm selecting the other button to measure. Timeline, a bit less clear. Record. Let's play the animation. And let's see our frames. There is no frames. This is because it's not running on JavaScript. You can't measure what is not running. This is happening on the GPU. So there's a few situations where JavaScript animations are still faster than CSS animation. But you can improve these things as much as you can improve things using the engine of the browser. So you can expect CSS animation to be much more performant in a year from now because of this. Because now browsers can make everything happen in C++ or whatever language the browser is down. And you have the performance. You are as performant as you can be. You have the main thread for your app, which is nice. And I have a bigger demo. This is the same app you have seen before. I have this, I click this, and I can move this around. And there is something I want to show because it's a very simple use case of how to take advantage of this new API to make things very easy. Look at this. I have this menu on the bottom. And as you see, I move it dragging around and I have this cross on the top corner being animated along with the movement. Let's see how I did this. Maybe. Maybe. No. Not this. Here. Let's open the slide menu. The slide menu HVS. No, the application HVS. And I think it's everything I need for now. I know. I need more things. The toggle menu and the overlay here. Let's put this on the side. If we look at the application HVS, we see that we have this slide menu. Yes, sorry. We have this a bit more. We have this slide menu, which is a component. And I deal some contents, which are the links that the menu contains. I also have this other component, the toggle menu, which is the button, the hamburger button on the top corner. And I have this overlay, which is basically, if you realize here, this is becoming darker because I have another layer on top of it. And I synchronize everything. In this case, I have this set of animation, which is called when this element is added to the DOM. And as soon as this element is on the DOM, I want to prepare the animation. So I cast the width because it's performance. And I create this animation. New animation is something that the polyfill provides you because you can, instead of calling element.animate, you can instantiate a new animation object and pass the element. The difference is that this doesn't start animation right away. If you do animation, the animation starts when you call document.timeline.play and you pass the animation to this. And I'm sending this animation with a send action to the controller. I'm doing the exact same thing here in this other component, which is the overlay. And the same thing, which only is in case animation, it's more complicated on the toggle button. And in the controller, it's application, maybe? Yes. I have this set of animation, which basically, it's time I receive animation. I push it into an array. And I schedule things on the after render because I know that in the after render, everything will be added. So I will have all the animations already prepared. And what I do is to create an animation function, which what it does is create an animation group. What I do is I create an animation group, which contains these three animations. And I command document.timeline.play this group. If I tied these animations together, they mean I have only one player to control them all. So I can move the animation back and forward, changing the time. And I'm basically calling this recursively on all the inner animations. So I can control every animation with only this little code. By example, in the slide menu, I have a few events. But this is the touch move event. I have an abstraction. You don't care about this, the gesture. To detect swipes, if the speed, something I did. But I just say this.player.currentTime equals some math I did to say, OK, this is the 50%. So I changed the time to the, if this animation is two seconds, I set 100 milliseconds. Sorry, 1,000 milliseconds. And I am in the middle. And everything is in the middle of the animation. So I can control things. And the same things work for sequences and everything. So you can have very complicated animations and control it very easily with one liners almost. And the other part is working offline. I hope, I really hope you like this icon. I learned how to use Adobe Illustrator just for this. What if I tell you that you can make your app work offline in 20 lines today? Only Chrome, but yes. They're introducing service workers who heard of service workers before. It's the best thing since Battle Cream. This is all the code you need to make your app offline. Everything. This is one of the approaches. There is a few approaches to make this offline. This doesn't work for every situation. But a service worker is a worker, like the web workers, which means it runs in a separate thread. But unlike workers that don't have network access or DOM access, but this doesn't have DOM access either, they are intended to intercept the main thread request. So if you perform a request from the main thread and you have a service worker register, and with this FetchEventListener, you will get, I mean, this code will be executed before the request actually outputs, goes out from the browser. That means that if I get this request, the requests that I streamed, that's why I'm cloning because I stream can only be read once. I'm cloning things. This is the request, the fetching request. Wait a minute. I don't remember. And this is, I want to respond to this request with an actual fetch to the server. So if I get 200k or I just get a request successful, I can, I have the cache, I fill the cache with this response and I return whatever I get. So that means I have just cached this response forever. I mean, if the content, if your content doesn't need to be cached because it needs to be updated, you can't use this, but, and if something fails, I try to read on what is on the cache. That means if I am on airplane mode, by example, and I try to access a web page where I have been before, first of all, I try to make the request, I have no network, then I look in the cache. It's in the cache. The user doesn't realize. It's served right away. And this is the code you need to register the worker. This offline support file contains these 20 lines. And a small demo is, again, this thing here. No. Here. This is the same app. I've been here. And I basically, I've been in all the pages. So if I go here and stop the browser, I go here and reload. It works. I mean, it's, I can navigate. I can go to everywhere. I can be here. Newspaper here. Change the animation to something different. Everything works because, and it's 20 lines. 20 lines of code. Sorry. It casts by URL. So yes, it includes the mine and port. There is a restriction to this. Like many other features coming into the web, you need to use HTTPS to have this thing available. Or be a local host, which is basically useless. This is how it works. You have the page. The page makes a request. The service worker intercepts this request and runs its code. Its code, what it does is basically makes a network request. And if I get a network request, I populate the cache and returns the very same request. If I don't have network, if this fails, I will hit the cache and return whatever is in the cache. And this is only one approach. There is a lot of other patterns. We can prefetch content in advance, because this, we can use the cache always and only fall back to the network when I don't have this thing in the cache. It's the opposite thing I'm doing. This is what I call the offline first. In the cache, this is the right content. Save things for later, like I read it later. I want to make this, I want to read this later. And based on a user interaction, I command the service worker to request this URL and store it for later. Or return whatever is in the cache and make the request in the background. So the next time I have the more data. So it's not very important to you to have the most up-to-date information as long as you are very fast. Or this is very cool. And it's not, we're not yet there, but this is very close. Listen for pass notifications, push notifications. Even when your app is close, because when you register a service worker, it's alive forever. So the browser is listening for post notifications or for messages from the server. And when you go back to your app, you have all the information there. Or you can use the native push notification service of your operating system to actually show things. There is very, very good blog post, kind of a cookbook for various types of Jake Archibald is a guy working in Google and kind of the main promoter of this technology. When you can see a lot of usages of this technology, even many, very, many crazy ideas like having your framework running on the thread. Because you can, on the initial request, maybe request a template, have some code that knows how to use this template. And from that point on, you request JSON, mount the HTML on the worker, and the request returns HTML. And you just display HTML. But it's possible. I have a bigger demo. I don't remember. Ah, yes, I do. The difference between this and something that exists in the past named App Cache is that you have full control of the request and the content. That is a very low-level API. That means that you can do pretty much whatever you like. And in this application, maybe you realize that here I have this sign. I know that I have no connection. And this is why, in the code, I close this offline support. This thing here. And I have this thing. When the request fails and I return something from the cache, if this request is from an endpoint that matches this regular expression, so the API, it's a JSON request, so I can open it, add information to this request. In this case, I add a meta offline support worker equals true. And send the request back. So I create a new request and send it. So basically, I intercept the request and add metadata to know, hey, this request has came from the cache. Deal with it in a slightly different way. And in my app, what I do is just every time in the app there, every time I receive a request, if it has this meta, I just enable this icon and that's it. I mean, it can be done, but this is just an example, but you can actually tamper your request and make things happen. So please don't wait. I mean, this is so, so powerful as something that you can start using right now. Even if Reynolds only works on Chrome and I think on Firefox behind a feature flag, it's, I mean, if it doesn't work, if, I mean, doing this feature detection, if it doesn't work, you just don't. And if it works, you have an offline experience almost for free. So go ahead. I mean, there is no harm. And that's everything I have.