1

Was poking around with serviceWorkers to cache some of the pages of my site (a rails app) so I was thinking of registering my serviceworker.js like so:

// Playing with serviceworker.js
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('/serviceworker.js', {
    scope: '/'
  });
}

But I realize that on production server (with https://) /serviceworker.js path will not be available.

So I was thinking how should I register serviceworker.js that's going to be fingerprinted and spit out via the assets pipeline?

Marvin Danig
  • 3,738
  • 6
  • 39
  • 71

2 Answers2

2

Assuming you have erb available on the views

You can put that code in a js.erb file then use like:

// Playing with serviceworker.js
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('<%=asset_path('serviceworker.js')%>', {
    scope: '/'
  });
}
Abs
  • 3,902
  • 1
  • 31
  • 30
  • > navigator.serviceWorker.register('<%=asset_path('serviceworker.js')%>' Those single quotes seem to be used incorrectly. It doesn't feel correct to serve serviceworker.js via the `app/erubis`. An ideal way would be via `config/environments` because of the way service workers work (https only et al), but I'm still thinking. In fact registering serviceworker and its implementation has nothing to do with app per se; service workers only intercept requests of a site and tells the browser where to serve the resources from - cache or actual host. – Marvin Danig Nov 17 '15 at 16:20
  • When you will run rake assets:compile and have a setting to precompile this js.erb file it is cached and precompiled to be served from normal asset pipeline something like this http://stackoverflow.com/questions/20275846/rails-wont-precompile-js-erb. Basically take care of different settings in [environment].rb and protocols and still be served the same way. Am I missing something here? – Abs Nov 17 '15 at 23:53
  • it does not work, because of security error. in chrome it's like: server worker registration failed: DOMException: Failed to register a ServiceWorker: The path of the provided scope ('/') is not under the max scope allowed ('/assets/bla/bla/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope. – Ali Ghanavatian Jan 24 '16 at 11:51
1

I'm running into this problem now as well. Based on my research, I think the proper way for a Rails application to handle service workers is to serve the service worker javascript file normally using the Asset pipeline, scope the service worker using the scope option, and then use the Service-Worker-Allowed HTTP header to explicitly allow the new scope (without this HTTP header, Service-Workers are restricted to only intercepting HTTP requests for pages under /assets/ in a standard Rails app).

Unfortunately, at the moment there are several barriers to implementing this method:

  1. Rails 4 (apparently) does not allow adding HTTP headers to Assets it serves, other than the cache-control header. To work around this you could add a Rack plugin as detailed in this S.O. answer, or in production if you are using an Asset server such as Nginx, you can get around this by having Nginx add the HTTP header. Though this doesn't help during development.
  2. Rails 5 does allow adding HTTP headers to Assets however, as detailed in this blog post.
  3. Browser support for service workers and the Service-Worker-Allowed HTTP header is currently poor.
Community
  • 1
  • 1
John
  • 9,249
  • 5
  • 44
  • 76