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.
(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).
(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
.
(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With