Caching, Font Awesome 5, and a Service Worker

I have a React site (Built with CRA’s PWA template) that uses Font Awesome icons and a Service Worker. When I attempt to change the size of the icons, I sometimes end up with a wrong, much larger result - I have specified 2x.

At one point, I even went so far as to remove the service worker code from my project to try and ensure the browser was not holding onto an old version of the icon.

I suspect this may be due to a cache issue, but am unsure how I should set this in my site’s netlify.toml. Part of the problem may be that my policy is effectively, ‘Use the cache but don’t trust it’ so the conflict between the old icon and the size I want to use is never resolved.

A check of the site now shows the icon to be correct, but I think is because the cached version expired, and it is not consistent.

How can I prevent this effect from happening and still use a Service Worker on my site?

# WWW
[[redirects]]
from = "/www.hirechrisfinazzo.com"
to = "/hirechrisfinazzo.com"
status = 301
force = false
# Netlify
[[redirects]]
from = "/https://gracious-babbage-21fe68.netlify.com"
to = "/hirechrisfinazzo.com"
status = 301
force = false
# Routing
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
force = false
# Plugins
[[plugins]]
package = "netlify-plugin-csp-generator"
  [plugins.inputs]
  buildDir = "build"
  [plugins.inputs.policies]
  defaultSrc = "'self'"
  fontSrc = "'self'"
  imgSrc = "'self'"
  styleSrc = "'self' https://use.fontawesome.com"
  scriptSrc = "'self'"
  connectSrc = "'self'"
  formAction = "https://formspree.io/f/xgerekvv"
  frameAncestors = "'none'"
  workerSrc = "'self'"

[[headers]]
for = "/*"
  [headers.values]  
  cache-control = '''
  max-age=0,
  public,
  must-revalidate,
  no-transform'''
  Upgrade-Insecure-Requests = "1"
  X-Content-Type-Options = "nosniff"
  X-Frame-Options = "DENY"
  X-XSS-Protection = "1; mode=block"

It depends on how your service worker is configured. I don’t know how you’re generating a service worker, but when I manually write one, I do something like this:

const cacheName = 'Cache v1';

self.addEventListener('install', event => {
  self.skipWaiting();
  // cache your files here
});

self.addEventListener('activate', event => {
  event.waitUntil(caches.keys().then(cacheNames => {
    return Promise.all(cacheNames.map(currentCacheName => {
      if (cacheName.indexOf(currentCacheName) === -1) {
        return caches.delete(currentCacheName)
      };
    }));
  }));
});

What this basically does is, as soon as the new version of the service worker gets activated, it deletes the old cache. This is made possible by the following:

  1. The name of the cache. All you need to do, is change the cache name string when you need to update the service worker in users’ browsers.

  2. Browser downloads the service worker file every time your website loads over the network.

  3. Because of skipWaiting(); the new service worker gets activated immediately.

  4. As soon as it gets activated, the activate event handler manages the task of deleting the cache of previous service worker. Considering you cache your files in install event, the new files will first be added to the cache before the old ones get deleted.

With this, you’d still see the old website after you publish the changes, but on subsequent reloads, the new changes will show up. This is because, even after a publish, the old service worker is responsible to serve files from disk, while after the new one gets installed it is available to serve the updated files.

Hope this helps.

I knew this looked familiar… Oy.

Turns out™, a prior version of the site (using Jekyll) implemented this function in a worker I customized and the initial version using React did as well. I guess we can just try again.

I still am a bit unsure if my icon syntax is correct and will look this up for v5.

For cache, I’m still thinking about what the right approach is - FYI, I’ve read Chris’ post from a while back, and this still appears to be how the system works.

^ Please correct me if I am off on this point.

It may make more sense to go back to just using only no-transform and leave the rest to Netlify’s backend.

You’re right, it still holds true. Netliy does what a server can to serve up-to-date content.

1 Like