The documentation for what maxAgeSeconds does, is pretty vague:
The maximum age of an entry before it's treated as stale and removed.
...so I did some manual testing and came to the conclusion that it must be calculating the "age" as the time since the resource was downloaded form the server. And because of that assumption, I created an entire feature request for maxUnusedSeconds which calculates the age as the time since the resource was last used on the page.
In practice, this means that the behavior of the ExpirationPlugin can drastically change based on subtle differences. As an example, if you save your images with the CacheFirst strategy and set maxAgeSeconds to a month, then as long as all your images are served with a correct Date header, they will all be removed and get a fresh update from the server at least once a month. But if you one day accidentally disable the Date header on your server, then the serviceworker will fall back to IndexedDB timestamps, which are updated every time the images are used, so if a user watches those images at least once a month for several years, then the images will just stay in cache and never be redownloaded from the server for all those years.
I believe the expected behavior is to always calculate the "age" as the time since the resource was downloaded form the server, and therefore you should make the IndexedDB calls adhere to that standard.
Hello new team :)
I found a bug in https://github.com/GoogleChrome/workbox/issues/2863#issuecomment-881791503 and decided now that it should probably have a separate issue.
Library Affected: workbox-expiration.
Issue or Feature Request Description:
The documentation for what
maxAgeSeconds
does, is pretty vague:...so I did some manual testing and came to the conclusion that it must be calculating the "age" as the time since the resource was downloaded form the server. And because of that assumption, I created an entire feature request for
maxUnusedSeconds
which calculates the age as the time since the resource was last used on the page.But now it turns out, the existing implementation is actually doing a bit of both. The lightweight
Date
check you're doing inisResponseDateFresh
is correctly determining the time since the resource was last downloaded from the server, but for theIndexedDB
check inexpireEntries
to also work correctly, the timestamp must only be updated when a new version of the resource is downloaded from the server, and that is not currently the case, since you callupdateTimestamp
as part ofcachedResponseWillBeUsed
: https://github.com/GoogleChrome/workbox/blob/46af63c1780955345c117c63c8c8dd54f3d40220/packages/workbox-expiration/src/ExpirationPlugin.ts#L162-L164In practice, this means that the behavior of the
ExpirationPlugin
can drastically change based on subtle differences. As an example, if you save your images with theCacheFirst
strategy and setmaxAgeSeconds
to a month, then as long as all your images are served with a correctDate
header, they will all be removed and get a fresh update from the server at least once a month. But if you one day accidentally disable theDate
header on your server, then the serviceworker will fall back toIndexedDB
timestamps, which are updated every time the images are used, so if a user watches those images at least once a month for several years, then the images will just stay in cache and never be redownloaded from the server for all those years.I believe the expected behavior is to always calculate the "age" as the time since the resource was downloaded form the server, and therefore you should make the
IndexedDB
calls adhere to that standard.