kimlai
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!
Most Liked
lucaong
I use the same strategy for the ServiceWorker on an offline-first production Rails + JS application with good results since years. While somewhat uncommon, there is no issue in rendering a JS file with EEx when needed.
Of course, LiveView needs some special care when it comes to offline behavior, and depending on your needs, being it a server-side tech, it might not be the best option if offline-first is a strong requirement.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








