Setting up Service Worker in Ruby on Rails

Setting up Service Worker in Ruby on Rails

Webworkers are most promising future of HTML5, get your Rails app ready.

A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction.

Service workers are isolated browser threads running in the background, in an entirely different context from the web page and therefore have no access to the DOM, the window or document object.

We have been using Service Workers on Pasilobus apps for some time now. Using service workers, we can intercept requests made by server at the browser level and trigger different actions or even serve a cached version of your app and users never get disconnected.

Service workers also allow for background sync, so even if the internet connection is lost, using service workers, your app can still process the data and sync back to the server as soon as the connection is restored.

Adding a service worker to a Rails app is easy. Start making a controller for it

class ServiceworkerController < ApplicationController
layout false

def service_worker

Then let's add a route for our service worker

# Service Worker
get '/service-worker.js' => "serviceworker#service_worker"

To call the service worker, we need to add a script to the asset pipeline, if you are using Rails 6 this should go to webpack and javascript folder:

# javascript/src/service_worker.js

// Use feature-detection to check for ES6 support.
function browserSupportsES6() {
try { eval("var foo = (x)=>x+1"); }
catch (e) { return false; }
return true;

// Use service workers only if the browser supports ES6,
// the Cache API and of course Service Workers themselves.
if (browserSupportsES6() && ('caches' in window) && ('serviceWorker' in navigator)) {
navigator.serviceWorker.register('/service-worker.js', { scope: '/' })
.then(function(reg) {
//console.log('Service worker registration succeeded!');
}).catch(function(error) {
//console.log('Service worker registration failed: ' + error);
# javascript/packs/application.js

import "src/service_worker.js"

This will register our service worker as soon as the user opens the app in browser.

And of course create a view file for the actual worker

# views/serviceworker/service_worker.js.erb

var CACHE_VERSION = 'v1';

function onInstall(event) {
// console.log('[Serviceworker]', "Installing!", event);
event.waitUntil( prefill(cache) {
return cache.addAll([
'<%= asset_pack_path 'application.js' %>',
'<%= asset_pack_path 'application.css' %>',

self.addEventListener('install', onInstall);

Our simple worker contains a function that is trigger on install event, and it tells the browser to cache assets and offline.html sample page that will be serve to the user when the connection is lost.

Let's also add our offline.html file

# views/errors/offline.html.erb

<h1>Hey I am page served by service worker.js<h1>

Service workers expire after a period of time, hence if you ever change the file, browsers will update service worker automatically.

When developing with service workers. Remember to disable them in the browser so they will not interfere with your work.

And that's all. Get started with workers and serve an custom offline warning page for your users.

Back to blog
1 of 3