USING
SERVICE
WORKERS
IN EMBER
John Kleinschmidt
EmberConf 2016
March 29, 2016
I’m so freakin’ excited! (source: http://bit.ly/1RqvzeD)
Hey everybody! Like Kristen Wiig here I am really excited to talk to you today about Service Workers because I believe they are the next evolutionary step in browsers. !In
the early 2000s XHR redefined what web apps could do and I see service workers as an even larger step forward. So let me start with telling you how I started working
with Service Workers…
For me it all started with kids like the ones you see here. !I work for an non-profit organization called CURE International and we provide life saving care to kids in 30
countries in the developing world. For the last 6 years we have been developing innovative technology solutions including real time reporting of kid’s statuses in our
hospitals, but we realized that we were lacking an essential tool across our network:
And that was a Hospital Information System so that we could provide better oversight of the care taking place in our hospitals & clinics. Historically our network has
relied on paper records and what you are seeing here is how patient records are transported to remote clinics. They are loaded into bins and then transported to remote
clinics.
Source: https://flic.kr/p/5wPfo8
Working in the developing world has its own set of challenges, and one of the most challenging items is internet connectivity. In some locations connectivity is really
poor or non existent. When we examined the available solutions, we couldn’t find anything that solved developing world challenges like oine, so we decided to build
our own:
HospitalRun: http://hospitalrun.io
So we built HospitalRun — a Hospital Information System for hospitals in the developing world. It is an open source system that we built for the approx 14,000 facilities
in the developing world that desperately need a solution like this. Built with Ember, Built for oine and online use; intentional focus on usability.#
When SWs became available, it became immediately clear that they were something that would be very useful for HospitalRun, so as we talk about SW, I will be
highlighting how they have been helpful in this project as well as to call out other uses in Ember applications
Source: https://twitter.com/jaffathecake/status/707139164488265728
So what exactly is a service worker? The spec says that it’s a “method that enables applications to take advantage of persistent background processing, including
hooks to enable bootstrapping of web applications while oine.” So let’s break that down a bit:
Source: https://flic.kr/p/5R3C5u
The second part of the definition says: ”bootstrapping of web applications while oine.” If you have heard of service workers before, chances are you’ve heard that they
have something to do with oine. One of the key features of service workers is that they allow you to run your web app oine. However service workers were not the
first browser feature to allow you to do this….
Source: http://alistapart.com/article/application-cache-is-a-douchebag
Application cache was the de-facto way of doing oine web apps. But it was painful to work with and didn’t give developers enough control due to its declarative
nature. App Cache has been called some not so nice things and for good reason. Service Workers were in part created as a response to the horribleness of Application
Cache, but to just talk about oine with Service Workers is just skimming the surface.
Source: !https://frinkiac.com/caption/S11E11/497960
Service workers really give us as developers the power. One way to think of a service worker is as network proxy that also allows you to control what happens with every
network request. Because service workers allow you to interface at the network level, you can run them on top of your applications without changing your existing
application code. There are several complimentary browser features that can be used with service workers:
Source: https://flic.kr/p/3xitmf
The first one is the Cache API. With this API developers have ultimate control of what gets cached and when. Also, you can programmatically pull items out of the cache,
so in essence you now have access to what used to only be available through browser internals.
Source: https://gauntface.com/blog/2015/02/11/fetch-is-the-new-xhr
Another complementary browser feature for service workers is fetch. You can think of fetch as xhr with promises. XHR doesn’t work in service workers, so you need
fetch to execute network requests.
Source: https://twitter.com/wanderview/status/699726998772572161
Getting back to our definition of service workers, there is a part I skipped and that is the first part of the definition which talks about “persistent background processing”.
It is important to remember service workers run in the background, but what exactly do we mean that it is running in the background?#
When service workers were first introduced they were called “Navigation Controller”, but the name was changed to include the term “worker”. This name is significant
because service workers are like web workers in that they run in a separate thread. This leads to some performance implications I’ll get to in a bit.
Source: https://flic.kr/p/pbLoro
Because service workers are workers this also means that they are essentially sandboxed - they have their own global script context, meaning they don’t have direct
access to your app’s code. Also, they have no access to the DOM. We can still communicate outside of the service worker via postMessages and the Cache API.
Let’s Encrypt: https://letsencrypt.org
AWS Free Certs: http://aws.amazon.com/certificate-manager/
There is one important caveat to using service workers and that is that they need to run under HTTPS unless you are using localhost. But I have good news — you can
get free certs from Let’s Encrypt and AWS, so you really have no excuse to not run HTTPS.
Is ServiceWorker ready: https://jakearchibald.github.io/isserviceworkerready/
So that’s an overview of ServiceWorkers. If you want to know more about service workers beyond what I mention in this talk, there are a couple useful references, the
first one being this site here, is service worker ready. This site has some good overview information and it also tracks what features are available in what browsers.
Service Worker Cookbook: https://serviceworke.rs/
Another useful resource is Mozilla’s Service Worker cookbook. They break down dierent use cases with live demos and source code.#
The chrome developer console is a valuable tool for debugging service workers as you can inspect and debug your service worker code just like any other piece of
javascript. The developer console also lets you see what is currently in the cache. Speaking of debugging:
SHIFT+REFRESH
Source: https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-container-controller-attribute
Something unexpected happened to me the other day. I was working on a project with service workers and I thought I had broken something pretty badly. It turns out it
was just a hard refresh on my browser which, I often do while debugging and I stumbled across something with service workers - a force refresh will disable the service
worker — it’s actually in the spec that way.#
So hopefully that gives you a high level understanding of service workers, but how should we be thinking of service workers in terms of Ember apps:
Source: https://twitter.com/tomdale/status/609791909922344960
Last year Tom Dale said that Service Worker should be something Ember apps get for free. I agree and it just so happened I was working on something around that time:
USING SERVICE WORKERS IN EMBER
ember install broccoli-serviceworker
Cost to you: $0.00
broccoli-serviceworker: https://github.com/jkleinsc/broccoli-serviceworker
And that was broccoli-serviceworker. Out of the box broccoli-serviceworker will setup your production builds to include a service worker that makes your application
available oine. And its completely free!
FIN!
So that’s it then - you now know how to use service workers in Ember…
FIN!
Wait… we are not done yet. Remember that I said that service workers were created in response to the horribleness of application cache? In particular one of the main
issues with application cache was that it didn’t give developers much control over what happened. Service Workers on the other hand are like….
Source: http://bit.ly/1MpFuEp
Choose your own adventure. When I was a kid I remember reading these books that were kind of like a computer game where you would be faced with a decision at
dierent points and depending on your decisions the story would have dierent outcomes. I don’t remember the one about a shark but that sounds intriguing! Service
Workers give you as a developer control over what happens. Let’s see how we can eect that control with broccoli-serviceworker:
broccoli-serviceworker oers several levels of chose your own adventure. The first is through configuration:#
precacheUrls - always serve these resources from cache. By default your app will be precached.#
fallback - provide a fallback path when oine#
networkFirstURLS - paths that should go to the network first; fallback to cache#
swIncludeFiles - allow you to pull in additional resources into SW
Service Worker Toolbox: https://github.com/GoogleChrome/sw-toolbox
toolbox.networkFirst - Pull from network first; fallback to cache.
toolbox.cacheFirst - Pull from cache first; fallback to network
toolbox.fastest - Pull from network and cache; fastest wins
toolbox.cacheOnly - Pull from cache or fail
toolbox.networkOnly - Pull from network or fail (default)
SERVICE WORKER TOOLBOX
broccoli-serviceworker includes Google’s Service Worker Toolbox which allows you to use express style routing with predefined network strategies. These strategies
reflect common patterns useful for service workers. You can use your app’s serviceWorker configuration to specify which urls use which pattern, or if you want to have
finer grained control…
You can add files to the serviceworkers directory in your app. Any file in this directory will be included in your app’s service worker. In these files you can use the service
worker toolbox to do some of the heavy lifting for you or you can roll with with own code as well. So now let’s look at some examples of how we can use service workers
in Ember:
Source: https://flic.kr/p/5wPfo8
As I mentioned earlier, one of the challenges we face with HospitalRun is working in contexts where internet connectivity can be spotty to non existent. Because this is
the case, we needed to be able to handle a user’s lack of connectivity gracefully in our app. Just adding broccoli-serviceworker lets us run our app oine, but we still
had to deal with the issue of a user trying to save or access data oine.
Source : https://github.com/HospitalRun/hospitalrun-frontend/blob/master/app/serviceworkers/
pouchdb-sync.js
To handle this particular issue we added code to catch specific network database calls. If those network requests fail, this code pulls the data from a local data store
instead. This process is seamless to the user (and to the app). The app thinks it is always getting a successful network request even while oine! Now you maybe
thinking that oine isn’t something you need to care about, but here are a couple of reasons to consider handling oine in your app:
“I had been thinking of Service
Workers as a tool to help in
situations where the user agent goes
offline. But of course it’s an equally
useful tool for when the server goes
offline. This was a nice reminder of
that. - Jeremy Keith
Source: https://adactio.com/journal/10186
1) Handling oine helps not only with user connectivity, but also with server availability…
Source: http://www.urbandictionary.com/define.php?term=lie-fi#image-3548222
A second reason to consider oine is our friend lie-fi. All of us have experienced that moment where we are connected to wi-fi, but we don’t *really* have a connection.
We can take that pain away from our users. Also, many native apps don’t handle oine very well and I believe that we as web developers have an opportunity to create
apps that work better than native apps because of the tools at our disposal.!#
Source: https://paul.kinlan.me/using-service-worker-server-side-adaption-based-on-network-type/
Even if oine isn’t a concern for you, the type and/or speed of your user’s connection may be something you need to be concerned about. If you have some information
about a user’s connectivity speed you can choose in your service worker what type of payload to request from the server.
Along those lines, for HospitalRun, we wanted to be able to monitor response times from the server so that we have an idea for a specific user what their experience with
the app is like. At some point we may add additional logic to better accommodate slow connections. So these are some use cases to consider when using service
workers to address network reliability, but there are some other things we can do with service workers:
Source: https://twitter.com/reubenbond/status/662061791497744384
As I mentioned earlier, because service workers run in a separate thread, there are opportunities to improve performance using a service worker. Typically our Ember
applications are single threaded, but with a service worker or web worker we now can use multiple threads in our Ember app
Source: http://nolanlawson.com/2015/09/29/indexeddb-websql-localstorage-what-blocks-the-dom/
One of the performance bottlenecks we had in HospitalRun was syncing between a local pouchdb in the browser and a couchdb server. It turns out that IndexedDB
which is used by pouchdb blocks the DOM and can aect performance.
Source: https://twitter.com/nolanlawson/status/692387067838500865
So we moved our pouchdb to couchdb synchronization to a service worker and immediately saw performance gains.#
Source: https://glebbahmutov.com/blog/run-express-server-in-your-browser/
Some people have gotten really creative about what they are doing in service workers… I even found this example where someone is running express inside a service
worker, in essence turning the service worker into a server. You could do this in an ember app today.
Source: https://flic.kr/p/2Wjmw6
The Future of Service Workers and Ember
So we have seen some examples of how service workers can be used in your Ember apps today, but as we think about the future of Ember and service workers where
are we headed?
Source: https://serviceworke.rs/push-rich_demo.html
One of the additional features that service workers enable are native push notifications. As you can see in this example, clicking a button in the browser fires a native
push notification. In the future your Ember application will be able to send these notifications.
Source: https://developers.google.com/web/updates/2015/12/background-sync
Another forthcoming feature enabled by service workers is background sync. The idea here is that actions can be deferred until the user has stable connectivity. In this
example, a user goes oine, sends a message, the user goes back online and the message is then sent. For certain Ember apps this will provide a way to queue up
updates without needing to build a queuing mechanism to sync oine updates.
Source: https://github.com/GoogleChrome/sw-unit-test-sample
Right now there isn’t a good way to test service workers in Ember. Command line testing via ember test relies on PhantomJS which doesn’t understand service workers.
But the fortunate thing is there is ground work available like this project which will lead to better testing of service workers in Ember.
Source: https://twitter.com/dstorey/status/694961349445554176
One of the things I didn’t mention earlier was browser support for service workers. Right now they are only available in Firefox, Chrome and Opera. But Microsoft is
working towards implementing them and…
Source: https://jakearchibald.github.io/isserviceworkerready/
Safari is considering service workers and have indicated in their five year plan that it is something they ”should” do. For a while I was discouraged into thinking that
service workers would never be tackled by Safari, but I now believe because SWs are such an evolutionary step forward, Safari will implement them
Source: https://www.fxsitecompat.com/en-CA/docs/2016/application-cache-support-will-be-removed
While we are talking about browsers something to keep in mind is that browsers are going to start deprecating and removing application cache support. Yehuda talked
about Application Cache in his keynote and while it is good to use today, we need to be prepared to shift to service workers. Firefox is the most aggressive here…
Source: https://twitter.com/jaffathecake/status/685595711401005057
But chrome is following their steps.
Sources: http://emberjs.com/logos/
Lastly when considering the future of Ember and service workers, I think we really need to start thinking about what it means to bring them into ember core. Because
ember-data is typically network centric, it makes sense that we would take advantage of multi threaded processing to speed things up there with service workers. Also, I
think that we will service workers used in combination with fast boot server side rendering to really speed up performance.
THE FUTURE OF EMBER AND SERVICE
WORKERS IS YOURS TO CREATE!
So that leads me to ask you a question: As you think about what we currently can do with service workers and what is coming in the near future, I want to ask you to
consider how you can use service workers and perhaps contribute that work to ember core or additional ember addons. As I mentioned at the beginning of my talk, I
believe that service workers are a huge evolutionary step forward for browsers - take advantage of that. And one more thing:
Find out more at: http://hospitalrun.io
HosptialRun is looking for volunteers to help us build an awesome app for the approximately 14,000 hospitals in the developing world that need a solution like this. #
You can find out more info at hospitalrun.io
Slides: http://jkleinsc.github.io/emberconf2016
Cover Image: https://flic.kr/p/hQannE
Source: http://gifs.joelglovier.com/thank-you/thank-you-zach.gif
Twitter: @jkleinsc
HospitalRun: http://hospitalrun.io