Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does sw-precache activation of new service worker guarantees cache busting?

I am using sw-precache along with sw-toolbox to allow offline browsing of cached pages of an Angular app.

The app is served through a node express server.

One problem we ran into is that the index.html sometimes doesn't seem to be updated in the cache although other assets has been updated on activation of new service worker.

This leaves users with an outdated index.html that is trying to load no longer existing versioned asset in this case /scripts/a387fbeb.modules.js.

I am not entirely sure what's happening, because it seems that on different browsers where the index.html has been correctly updated have the same hash.

On one browser outdated (problematic) Index.html

(cached with 2cdd5371d1201f857054a716570c1564 hash) includes:

<script src="scripts/a387fbeb.modules.js"></script>

in its content. (this file no longer exists in the cache or on remote).

On another browser updated (good) index.html

(cached with the same 2cdd5371d1201f857054a716570c1564) includes:

<script src="scripts/cec2b711.modules.js"></script>

These two have the same cache, although the content that is returned to the browsers are different!

What should I make of this? Does this mean that sw-precache doesn't guarantee atomic cache busting when new SW activates? How can one protect from this?

If these help, this is the generated service-worker.js file from sw-precache.

Note: I realize I can use remoteFirst strategy (at least for index.html) to avoid this. But I'd still like to understand and figure out a way to use cacheFirst strategy to get the most out of performance.

Note 2: I saw in other related questions that one can change the name of the cache to force bust all the old cache. But this seems to beat the idea of sw-precache only busting updated content? Is this the way to go?

Note 3: Note that even if I hard reload the browser where the website is broken. The site would work because it would skip service worker cache but the cache would still be wrong - the service worker doesn't seem to activate - my guess because this specific SW has been activated already but failed at busting the cache correctly. Subsequent non-hard-refresh visits would still see the broken index.html.

like image 724
mkhatib Avatar asked Oct 30 '22 08:10

mkhatib


1 Answers

(The answers here are specific to the sw-precache library. The details don't apply to service workers in general, but the concepts about cache maintenance may still apply to a wider audience.)

If the content of index.html is dynamically generated by a server and depends on other resources that are either inlined or referenced via <script> or <link> tags, then you need to specify those dependencies via the dynamicUrlToDependencies option. Here's an example from the app-shell-demo that ships as part of the library:

dynamicUrlToDependencies: {
  '/shell': [
    ...glob.sync(`${BUILD_DIR}/rev/js/**/*.js`),
    ...glob.sync(`${BUILD_DIR}/rev/styles/all*.css`),
    `${SRC_DIR}/views/index.handlebars`
  ]
}

(/shell is used there instead of /index.html, since that's the URL used for accessing the cached App Shell.)

This configuration tells sw-precache that any time any of the local files that match those patterns change, the cache entry for the dynamic page should be updated.

If your index.html isn't being generated dynamically by the server, but instead is updated during build time using something like this approach, then it's important to make sure that the step in your build process that runs sw-precache happens after all the other modifications and replacements have taken place. This means using something like run-sequence to ensure that the service worker generation isn't run in parallel with other tasks.

If the above information doesn't help you, feel free to file a bug with more details, including your site's URL.

like image 187
Jeff Posnick Avatar answered Nov 09 '22 23:11

Jeff Posnick