I'm starting work on integrating ServiceWorker scripts with the asset pipeline, and I'm wondering if there are workarounds for some issues I'm seeing. (Service Workers are a new web feature that gives developers intimate control over how requests are handled; among other things it can be used for building Offline-First web apps.)
One of the properties of a service worker is that a service worker can only control the subdirectory where the script is hosted. A trivial setup would only allow the Service Worker to control the /assets directory. It's preferable to host the script in the root of your domain, so your entire app can be controlled.
I've considered simply placing the script in /public, but that loses all of the features of the asset pipeline. Currently, I've setup a route/controller that reads the script from the sprockets environment and serves it through a controller action. I'm not sure if this would work in a default production setup.
Are there any other ways I could make a script available from the domain root that works reasonable well in development and production?
302 Redirects are not supported. The final path needs to be in the domain root.
I didn't have any issues with fingerprinted files.
Great question @whitehat101.
I've been following SW pretty closely but haven't deployed it in any of my applications myself. So theres a lot of new territory here.
Like you mentioned about path constraint, SW aren't really designed to be hosted on CDNs. This definitely makes them a little different then the preferred way Sprockets likes to deal with assets.
SW also have way different caching semantics. They need to be requested by the same url to check for upgrades. This means you can't really use fingerprinted filenames. Its really gotta be just /sw.js on your domain.
Again, I haven't deploy this stuff myself yet, but was thinking that having these requests go to the Rails app doesn't sound like that bad of an idea. I was also thinking that could play better into the bootstraping and upgrade process. You could make the main entry point a shell to load the actual script from the cdn. So something like:
// GET /sw.js
Whats nice is that the immutability of the CDN asset still works with SW cache check. It will fetch sw.js, see that the external source is byte for byte identical and use whats cached. To upgrade, it will see a new fingerprint and initiate the upgrade process.
The only downside of this is thats its another request. All of this is in the background for SW, so maybe that bad.
There's now a gem, serviceworker-rails that will allow you to proxy requests for serviceworker scripts in the asset pipeline.
With serviceworker-rails, a request to /serviceworker.js will respond with the corresponding fingerprinted, compiled asset in production. In development, you get the auto-reloading behavior you would expect. You can set up multiple serviceworkers at different scopes as well.