Registering and Installing a Service Worker in Rails
To use a service worker in a Rails application, we need to follow a structured approach:
- Create a service worker file to define caching behavior and event listeners.
- Register the service worker in the front-end code.
- Ensure Rails serves the service worker file correctly.
By integrating service workers, a Rails PWA can intercept network requests, cache assets, and provide an offline experience.
1. Creating the Service Worker File in Rails
In a Rails application, service workers should be stored in the app/assets/javascripts
or app/javascript
directory, depending on whether the app uses the asset pipeline or Webpacker/esbuild.
Basic Service Worker Script
Create a new file:
touch app/javascript/service_worker.js
Now, open service_worker.js
and define basic event listeners:
const CACHE_NAME = "rails-pwa-cache-v1";
const ASSETS_TO_CACHE = [
"/",
"/offline.html",
"/assets/logo.png",
];
self.addEventListener("install", (event) => {
console.log("Service Worker installing...");
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(ASSETS_TO_CACHE);
})
);
});
self.addEventListener("activate", (event) => {
console.log("Service Worker activated.");
event.waitUntil(self.clients.claim());
});
This service worker:
- Defines a cache storage key (
CACHE_NAME
). - Caches specified assets when the service worker is installed.
- Takes control of all open clients upon activation.
2. Registering the Service Worker in Rails
Once the service worker script is created, it must be registered in the browser so that it runs when the PWA is loaded.
Modify app/javascript/packs/application.js
(or app/assets/javascripts/application.js
if using Sprockets):
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/service_worker.js")
.then((registration) => {
console.log("Service Worker registered with scope:", registration.scope);
})
.catch((error) => {
console.error("Service Worker registration failed:", error);
});
});
}
This code:
- Checks if the browser supports service workers.
- Registers
service_worker.js
when the page loads. - Logs success or failure messages to the console.
3. Serving the Service Worker in Rails
By default, Rails does not serve JavaScript files from the app/javascript
directory as static assets. To ensure the service worker is accessible, we must explicitly serve it through a controller.
Adding a Route for the Service Worker
Modify config/routes.rb
:
get "/service_worker.js", to: "service_worker#show"
Creating the Controller to Serve the File
Generate a new controller:
rails g controller ServiceWorker
Modify app/controllers/service_worker_controller.rb
:
class ServiceWorkerController < ApplicationController
def show
response.headers["Service-Worker"] = "script"
render file: Rails.root.join("app/javascript/service_worker.js"), content_type: "application/javascript"
end
end
Ensuring Rails Includes the Service Worker File in Precompilation
If using the asset pipeline, add the following to config/initializers/assets.rb
:
Rails.application.config.assets.precompile += %w[service_worker.js]
4. Testing the Service Worker
1. Start the Rails server:
rails s
- Open the browser and go to Developer Tools > Application > Service Workers.
- If registered successfully, you will see
service_worker.js
running. - Try disabling your internet and refreshing the page—cached resources should still load.
Now, the Rails application has a registered and running service worker. Next, we’ll explore handling service worker events for better caching and offline support.