 Hello, dear developers! Let's talk today about the background services available in the modern browsers for us to build webfront applications with improved user experience. In my session, we'll go through the list of available background services and I'll also explain how to use this superpower for organizing the best-in-class webfrontend applications. My name is Maxim Salnikov. I work as a developer engagement lead at Microsoft Norway. And I'm a big, big fan of the modern webfrontend development. To share my knowledge, to share my passion and expertise with this area, I organize multiple meetups and conferences and I'm often speaking and presenting at events like conferences, meetups, workshops, hackathons, all for the technical community. You can find me on Twitter, WebmaxRU. I tweet mainly about web platform, about progressive web apps, service workers and everything around. I'll be happy to stay connected with you. Back to our topic. What is the current state of web platform in terms of what can we do for our frontend part of web project? Well, we can provide some functionality which was never available on the web before. For example, we can keep our webfrontend application and data it consumes always fresh. Or we can organize notifications for some future point in time, regardless of the connection status. So we somehow can inform our dear users about some scheduled event, regardless of their connection status. Or we can automatically replay requests which were failed for whatever reason. For example, when our dear user suddenly went offline. Or we can provide long fetches which are connection resilient. I mean, of course, we cannot have any magic secret internet channel, but at least our fetch will not be canceled if something went wrong with the connection. It can be paused, it can be continued after, so very good user experience. You can tell me that some of these points we can implement in our JavaScript code in our frontend application without any need to learn background services, without any need to use service worker. Some of them with one limitation. This functionality cannot work after user closed the tab with our application. So the code we have in our main JavaScript bundle will disappear right after our application tab was closed. But not with the background services. We can have all these features available in the background. This is why it has a name like this, right? And I will explain how this works. But first, what is a background service? This is a part of the browser, of the browser's engine, which allows us to write and run a code which will work in the background. And of course this code is quite specific in multiple terms compared to our main JavaScript code. First, it runs in a parallel thread, parallel to our main thread. It's always good because this way we have less competition for processor resources, for memory, so it allows us to build smoother and faster UIs. It has completely different life cycle. As I already mentioned, life cycle of the main application thread is quite trivial. We start our JavaScript code right after the user opens the tab and detects our URL and some first bytes of our JavaScript bundle were fetched and we close everything, we unload from memory everything right after user closes the tab or maybe the browser itself. It's not applicable to the code we have as a part of background services. It started by a completely different occasion, which is event. So basically everything we have in our background services is a reaction to this or that event. So event came, our code ran and then this code disappears. So background services is not something that we want to run for too long. So it's a fast and short reaction to a particular event. There are multiple reasons for this and I believe the main one is we don't want to overuse the resources of the browser for running code, which is part of background services. Just imagine if every application will register something that will run for long in background. Well, nothing left from processor time and memory. Another very important part of this difference is the fact that this code is always ready to, let's call this wake up, regardless of the state of the main application itself. So the code can wake up and run even when the browser itself or to be more precise, its visible part is closed. And looking at these parameters, I have an analogy with Phantom or Ghost because our application is dead, it doesn't exist in memory and the tab application is closed. But pieces of this application, which we have as a part of background services is waking up here and there, they live their own very short life and then magically disappears, like Ghost, like Phantom. What kind of events can wake up our code, which is a part of ServiceWorker, of course? First, everything connected to the network state. For example, the situation when we go from offline state to online state. There is a corresponding event, which we can receive in our ServiceWorker and write corresponding code. Of course, in that case, we are mainly talking about the code which will try to replay failed request, which we tried to do while we're offline. Also, if we do a long fetch, if we download some bulky resource, it will also send us statuses to ServiceWorker. Is it succeeded or failed and what is their progress? Next is family of events based on timings. Specific timings or some intervals will have a closer look on this in the next chapter of this slide deck. And of course, we can wake up our ServiceWorker from the backend. Here we talk mainly about web push notifications. I already mentioned that all the code we have as a part of background services intended to be located at ServiceWorker, inside ServiceWorker. Basically, this is the only place of our application where we can get life cycle we need, which is completely separate from the main thread, and this is the only place where the code is always on duty, regardless of anything. And multiple sources can send events to our ServiceWorker. First, application itself. Then browser. Then operating system, proxy via browser. Then internet. Again, here we go back to the case with push notifications. But how can we react? What kind of payload, what kind of code can we write in the ServiceWorker to provide better user experience? First, we can organize bidirectional communication channel between ServiceWorker and application. For example, to update number of unread messages on our UI if we build something like mail client or news client. But what if the type of application is not open? What if it's only ServiceWorker who is always on duty? Well, we can start the browser and open this application from our ServiceWorker and maybe then to organize this bidirectional channel. Or maybe for some scenarios we don't need to do this, let's say, obtrusive action like starting the browser. Maybe we just want to show the notification. It's possible. Yeah, in that scenario we only need ServiceWorker. And maybe the most interesting scenario when we can run some custom code without any kind of user notification. I mean, we do not start the application itself. We do not show any notification. Sounds a bit scary, but I'll explain you why it's still cool. Back to background services. How to find the list of what's available in the particular browser? First, it's not a surprise that majority of these services are only implemented in Chromium-based browsers. Basically, if we look at this list, only push messaging is also implemented in Firefox browser. How to find this list? There are tools, application tab and somewhere on the left-hand side in the bottom you'll find this list. Of course, as any part of DevTools, it's very convenient and very important for us developers because this particular piece of DevTools helps us to debug these background services which might be non-trivial task at all without this special feature of DevTools. As I mentioned, it's all based on the events and sometimes it's very challenging to predict when this event will come and in which form and what kind of reaction will be provided from service worker side. DevTools gives us a chance to record all these events, which is super convenient for testing and debugging. Okay, let's briefly go through this list. I'll explain you what kind of services are those and we'll stay on couple of them to have more details. Let's start with API called PaymentHandler. It's quite niche one for the scenario when you wish to build web-based payment service even more precise, heavily web-fronten-based payment service. It's uniqueness in the fact that I believe it's the only API and only possibility to install service worker on the fly without even visiting the origin of this particular service worker with multiple limitations, but still it's quite interesting feature. And mainly we use this API for managing UI of the payment services. Background sync, I already explained the scenario when user in offline do some actions and for example they write blog post and then they hit button post or send and there is no internet connection at this particular moment. So instead of showing server not found or some other error what we can do, we can preserve the data and register a synchronization. And then at the first occasion when online is back when the connection is available the code we wrote within this particular event listener will happen and in this code in many cases we just repeat the fetch for example sending this data to our API. And as I mentioned before this will happen automatically in the background even if the user closed the tab even if they completely forgot that something went wrong. Of course I think it's a good idea to provide some UI notification about hey now we cannot send your data to the servers and it will be delivered later automatically. It's the main power of this particular API. Background fetch gives us possibility to detach data fetching process from the application lifespan from the main thread of the application lifespan. For example we want to download some large resource some mp4 video file and the download started and then user for example decided to close the application or something bad happened with the internet connection again then we have all the tools to for example pause this download and then to continue with this when it becomes possible. So we'll have the UI very similar to UI we have for let's say classical download using anchor tag. At the same time what differentiates this way to download resources from the one with anchor tag we have full control over the bytes downloaded. So it's not just the next file on our operating system which was downloaded. No, we have these bytes available in our JavaScript code and we decide what to do. In cases we just want to put them into cache storage for later usage from our front-end code. Push messaging. It's the most mature API from that list and here I just want to remind that we have possibility in addition to showing the notification itself to also run custom code. So we are closing to running custom code as a background task but in that case we must show the notification. So there is no chance for us to organize this in invisible for the user way. Okay, what's left? Notifications. On the one hand it's the best friend of push messaging API. As I mentioned there is no sense in sending push notification without showing the notification itself. But hereafter we'll talk about different part of this API called notification triggers and both notification triggers and periodic background sync are time-based activities we can run as a part of background services. I believe this is the only what makes them similar and they have very many differences. I gathered full table of this to better explain these APIs. First, what are they designed for? Periodic background sync. It's to give a chance to the developers to organize refresh of the application and data it consumes in the background. That means that it only makes sense to run this code and to send this event to the service worker while the user is online. Notification triggers is designed to give us developers a chance to schedule some notifications for the future time regardless of the connection. Okay, let's go through some of the parameters. Timing. As the name of this API says periodic background sync is something based on intervals. While notification triggers we schedule this trigger, this notification for one particular time stamp in the future. What can we do here and there? In PBS we write the custom code itself so there is no any magic way for having our application fresh and data it consumes fresh without the code we write ourselves. We just have this trigger when to run this code. Notification triggers is limited to only show the notification. Visibility for the user. PBS is completely transparent. I mean it happens in background. If we don't want to inform user about some code is running we do not inform user. In notification triggers obviously notification is intended to be visible it's native browser's notification. If we look at these three criteria these three descriptions of periodic background sync. Once scheduled it will run for more or less forever until user explicitly deregister this or maybe reinstall browser from scratch. We can have custom code there within this event handler. Hello Bitcoin mining. And this will happen all completely invisible for the user. Sounds scary, right? It's exactly the custom code I mentioned in my slide where I describe sources of the events. This is why there are multiple limitations and multiple considerations about this API about the case when this event can ever come to the service worker. First and foremost the final decision maker on send or not send this event to service worker is the browser is what we call user agent and it takes decision based on multiple parameters. First connection. I already mentioned that it all makes sense for KBS to run in online only. It was designed to run like this while maybe the main power of notification trigger is for offline mode when we don't have any chance to reach out to any particular user device for example to wake them up if we build some web front end based alarm clock. So notification triggers will work both online and offline. Pre-requisites needed to ever run this code as a part of these APIs. Notification triggers it only requires permission for showing notification like we have for web push while it's way more serious for PBS. First there is separate explicit permission required from user side to run this code in background and second maybe even more important is the fact that application has to be installed on user machine. Luckily these days it's quite simple to organize installation of your web front end application using web app manifest using the fact that browsers are well integrated with operating systems now but still it's quite a serious current. Also what I not listed here but also very important this event as a part of periodic background sync will come to the service worker only on the same network where it was registered let's say it's the same Wi-Fi network for example again it's designed like this to not break the user privacy. Let's have a look at some code. Periodic background sync it all starts from the registration of this particular sync or periodic sync to be more precise. In majority of the scenarios we do it in our main JavaScript bundle and I always recommend to do feature detection because this API might be available or might be not available under particular circumstances and we don't want to pollute our console with red lines and we definitely don't want to ruin core user experience and then we provide only one parameter called mean interval so we don't have full control over these intervals where we want to receive this event in our service worker we only can say something like hey please do not send this event more often than 24 hours for example and what's next? Next we go to the service worker and inside service worker we receive periodic sync event if we are lucky, if all these conditions are true and what's next? Next we write our own code there is no magic which will help us to update the application we have to write everything manually in majority of scenarios you fetch for example updated version of the application shell maybe you trigger some API endpoints to keep the data it consumes only also fresh and I think that if we receive this event we are already lucky but we can do step further towards best user experience and do extra checks before running our update code for example we can check network connection type and only run this update when we are on fast stable network maybe the user in data saver mode and then I suggest we can skip update at all and after all if we are talking about fetching some data maybe it's good idea to check if there is space available on the user's device if we talk about timing how often can we receive this event if we only provide a minimal interval in the best case scenario it's 12 hours and by the way it's something that's not part of the specification every browser decides themself what is this let's say timing schema what it depends on engagement score this is artificial index calculated by the browser and it's about how long and how often the user interacts with your application so the browser tries to do the best guess how popular your application is for a particular user to decide on how much resources it might dedicate to this particular application if we look at the notification triggers it starts also in the main thread and same I strongly recommend to start with feature detection and by the way here I illustrated how this notification might look like on Windows 10 operating system here we specify exact time point when we want to show this notification and then as a trigger we provide time stamp trigger and maybe in the future we'll have more triggers not only based on timing but maybe based on geolocation maybe based on some other parameters so I hope I inspired you to have a closer look on background services and maybe on these two specific APIs what's about availability and behavior of these APIs on particular browsers and on particular operating systems I have a long answer for you it really depends platform and operating system browser and its version browser settings and even flags and after all origin itself and the fact is application installed or not you can get all these details about every single browser and every single situation on the links I mentioned on this slide but I have a shorter answer for you let's just think about these features like part of progressive web application and P in this acronym means progressive in terms of progressive enhancement so let's just think about these features like about something that might improve user experience and it might happen or not and of course technically feature detection is the mechanism where we check all these availabilities let's sum up the goal of these APIs and many other APIs which are part of service worker family is to catch up with what native code can do and in some scenarios the web can do even better than native code these days let's really keep user experience in the focus and by using these APIs we give something in terms of better features more convenient usage of the application but we require something in return multiple things first all these annoying permissions second all security and privacy considerations third consumption of resources needed for running these background services so let's together with authors of these specifications find proper balance between what we give and what we require in return when it comes to developer experience I'm super happy with the current situation we have web standards we have great tooling and what I'm super happy about it's just a beginning of this great great journey I invite you to join Open Slack team I organized few years ago where we have more than 2,000 developers now discussing PWAs, service workers, background services etc and on that thank you very much