Pre-caching assets with a service-worker

Hi everyone,

I’m trying to add a service worker to a Phoenix 1.5 app to display an offline page when the user has no network connectivity. To do this I need to cache some static assets (css, fonts and an image) along with the html page itself.

Following this cookbook, I would need something like

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('pre-cache:v1').then(function(cache) {
      return cache.addAll([
        '/css/app.css',
        '/images/logo.svg',
        '/fonts/some-font.woff2',
        '/offline.html',
      ]);
    })
  );
});

Since I’m using Phoenix, my static assets are “digested” using mix phx.digest when the app is deployed to production, so I need to cache the files using their hashed names. I also want the service worker to work locally, where the filenames do not contain a cache-busting hash. I also would like to avoid adding a build step. Something like workbox would require to run their cli after mix phx.digest has run, so it’s quite awkward to make it work in conjunction with webpack to get reloading etc. when working locally (I did something like this in the past and it was not great to work with).

Basically I need a way of getting the name of some assets, with the hash in production, and without the hash locally, which is exactly what Routes.static_path/2 does, and put the result inside a javascript file.

So what I came up with it to generate the service-worker.js file using EEx by doing this:

# router.ex
  scope "/", MyApp do                                                                                         
    get "/service-worker.js", SomeController, :service_worker                                                     
  end  
# some_controller.ex
def service_worker(conn, _) do
  conn
  |> put_resp_content_type("application/javascript")
  |> render("service_worker.js")
end
  # service_worker.js.eex
...
  caches.open("pre-cache:v1").then(cache => cache.addAll([                                                                                                                  
    "<%= Routes.static_path(@conn, "/css/app.css") %>",                                                                                            
    "<%= Routes.static_path(@conn, "/images/logo.svg") %>",
    "<%= Routes.static_path(@conn, "/fonts/some-font.woff2") %>" 
    "/offline.html",                                                    
  ]));   
...     

It seems to work nicely, but I don’t think that I’ve ever seen EEx being used to render anything but html, so I’m wondering if I missed something here (security issues, or a simpler way of doing this).

Thanks!