Today we’ll take a look at using Pusher in a Service Worker.
A Service Worker is a script that sits between your browser and the network, allowing you to respond to any requests made from your frontend. This can be used to serve content to users when they don’t have an active internet connection.
Step one – build it all
Service Workers act as an enhancement to an existing site, so you don’t have change the way that you build your frontend (although, you do have to serve your final site over https).
So, we’re going to start by ignoring our service worker and creating the site. To do this, we’ll make a web server that provides two urls:
GET /json – pull the most recent tweets from a database, and serve it as json
GET / – give us some stuff to fetch the json and render it nicely
Here’s how we might implement it as a node.js application (full source on github):
app.get('/json', (req, res, next) =>
.lrange( 'tweets', 0, -1 )
.then( result => result.map( JSON.parse ) )
.then( tweets => res.send( tweets ) )
.catch( next )
// expose / (index.html) from file system
(note, the database is populated by a second script)
Now we can deploy that online somewhere and we’re all done! We’ve got our page that displays the recent tweets.
Taking our app offline
Our next step is to make our application available offline. We can do this by writing a Service Worker script (this will be a new script that register from our main page).
We want to request our two urls and store them in a cache, we can do this by calling
cache.addAll when the service worker first starts up (firing the
Once installed, we can respond to any requests from the page by hooking into a
self.addEventListener('install', (event) =>
self.addEventListener('fetch', (event) =>
Lastly, we need to register the service worker in our frontend:
And now we’re all cool. Now we’re able to see our tweets even if we’re offline!
(still looking the same, but now it works offline)
Keeping things up to date
We have a problem. As our
/json endpoint is updated, the frontend will still be see the cached version without any new tweets.
To handle this, we can change our caching policy to include a network request. (sw-toolbox is a great way to set up caching policies.)
Though, using the new pusher-js, we have another option, we can open a connection from our service worker and update the
/json cache as soon as new data comes in.
const add = (tweet) =>
.then(resp => resp.json())
cache.put('/json', new Response(
This means that our cached version will be updated, without actually making any requests to the web server – which is kinda nuts when you think about it.
We can deploy this, and now our
/json endpoint will be updated with new content as it comes in.
(still the same, but now it actually works.)
Note: there are other ways of getting data into a service worker – check out background sync and push notifications. The way we’re using Pusher here is slightly different from both.
Notifying users of new data
If we’re pushing things out to the user, we might as well notify the user of there being more content. A common way of doing this is to show an “X more things” label at the top of the feed.
We can subscribe to messages in our page by adding an event listener to
And from the service worker, we can publish a message to all clients that are using this service worker:
.then( clients =>
clients.forEach( client =>
And we’re done.
Something interesting about this is that although our page is seeing realtime data – the only connection to pusher is within the Service Worker, meaning:
- there won’t be any re-connects when we reload the page.
- no matter how many windows/tabs we open – we’ll only need one connection or message to notify them all.
You can see the live site deployed at pusher-tweet-list.herokuapp.com, and the source code can be found on github.com/pusher-community/tweet-list
If you’ve got any questions/comments – I’d love to hear them, give me a shout on twitter at @benjaminbenben.