I am using the gatsby-plugin-offline plugin and would like to know if there is a way to handle updates.
I would like to display a message if a new version is available like
https://medium.com/progressive-web-apps/pwa-create-a-new-update-available-notification-using-service-workers-18be9168d717
At the moment I need to hard reload the site in order to see changes.
How to handle this?
Thanks in advance!
Same here
Right now workflow is like that - when there is SW update, gatsby will just set flag to reload page on next navigation (so it doesn't refresh itself which would cause weird UX)
You can hook into onServiceWorkerUpdateFound browser API hook
in gatsby-browser.js
if you want to display custom message, so users are aware of it (or even force refresh if you would want that)
@pieh do I understand correctly, that with every new gatsby build the service worker gets the update and I don't need to worry about my users getting an old version of the webiste? I couldn't find anything about it in the gatsby-offline-plugin docs.
@rwieruch Same problem here. On libresat.space (sources here), the old content still gets served (deployed using Netlify). Some docs would be awesome.
Well, found it out. It's very simple actually!
Just add the following to gatsby-browser.js
in the root of the repository (no further config necessary):
// gatsby-browser.js
exports.onServiceWorkerUpdateFound = () => {
if (
window.confirm(
"This site has been updated with new data. Do you wish to reload the site to get the new data?"
)
) {
window.location.reload(true);
}
};
This shows a little modal that reloads the site if the user pressed "Yes". See learn-chinese.tk (sources here) for a demo.
bad UX in my opinion, the user will keep seeing modals every time a new content is available
I think I will just disable the offline plugin before launching a new website/application. Heard about too many launches that went wrong or website still serving old content due to service workers. Not necessarily related to Gatsby, but maybe just avoiding service workers for now is a better option.
Well, another option would be to simply reload the page without any confirm:
// gatsby-browser.js
exports.onServiceWorkerUpdateFound = () => window.location.reload(true);
I prefer the modal though. I've seen this a lot on other sites as well - on a slow mobile connection you don't want to reload the whole page, after all that's what serviceworkers are for!
The discussion in this thread has been helpful - thanks!
Using the method in the previous comment, I'm seeing the following behaviour after service worker update:
I would expect the content to be updated in step 2. Am I missing something?
My code (from @pojntfx's comment above):
// gatsby-browser.js
exports.onServiceWorkerUpdateFound = () => window.location.reload(true);
I would actually prefer the user alert method, but this turned out to be problematic because of https://github.com/gatsbyjs/gatsby/pull/10432#issuecomment-447098098.
Hi @laradevitt, I believe the problems you've described should be fixed in #10432 - hopefully this should be merged soon so please could you have another look once this is ready? Thanks!
@davidbailey00 - Thanks! Yes, I mentioned that PR above. Was looking for a quick fix in the meantime but I guess I should just be more patient. :) If there is anything I can do to help test, let me know.
Hey, @davidbailey00 - Noting that #10432 had been merged I updated all packages and the problem as described in my previous comment no longer exists.
I'll note here, in case somebody else stumbles upon this issue, that this:
exports.onServiceWorkerUpdateFound = () => window.location.reload(true);
should now be:
exports.onServiceWorkerUpdateReady= () => window.location.reload(true);
Works a charm. Thx. :)
Hey, @davidbailey00 - Noting that #10432 had been merged I updated all packages and the problem as described in my previous comment no longer exists.
I'll note here, in case somebody else stumbles upon this issue, that this:
exports.onServiceWorkerUpdateFound = () => window.location.reload(true);
should now be:
exports.onServiceWorkerUpdateReady= () => window.location.reload(true);
Works a charm. Thx. :)
I dont get it... do I need both handlers?
@diegodorado No, the second replaces the first.
@rwieruch Same problem here. On libresat.space (sources here), the old content still gets served (deployed using Netlify). Some docs would be awesome.
That is the same issue I am having, cache is not updating new content, annoying as hell.
it's interesting since when I do npm run build
it shows for any of the solutions above
ERROR #95312
"window" is not available during server side rendering
@cxspxr - AFAIK code in gatsby-browser.js shouldn't be applied during build time. Is that where you're putting it?
@laradevitt yes. It's strange but problem resolved on freshly cloned project. No tracked changes in old folder
A good habit that saves me a lot of headache on Gatsby projects is to always use typeof window !== "undefined" && window
instead of just window
I frequently observed troubles with gatsby-plugin-offline
after site updates (white pages with errors or stale content (some parts missing or mixed up). A force reload solves those problems, so I wanted to do it regardless of any user input, but at the same time, I wanted to have some feedback mechanism in place to inform the user about the site update.
I used the Notification API so that it is opt-in and non-invasive for the user (unlike alert
and confirm
, which are modal).
looks like this on Windows 10
The implementation looks as follows, in case anyone is interested:
import { ServiceWorkerArgs } from "gatsby"
export const onServiceWorkerUpdateReady = async (args: ServiceWorkerArgs) => {
const permissionResponse = await Notification.requestPermission()
if (permissionResponse === "granted") {
await args.serviceWorker.showNotification("Website update", {
body:
"Our website just got a little bit better. We reloaded the site with the update to ensure a smooth experience for you."
})
}
window.location.reload(true)
}
You can find information about adapting the behavior of notifications here. In case you wonder how to use TypeScript for Gatsby APIs, the most comprehensive real-world example I know is this website.
I have the same issue. I need to perform a hard reload on the page to get new content.
I've tried adding this to gatsby-browser.js:
export const onServiceWorkerUpdateReady = () => window.location.reload();
...but with no success. Still need to perform a hard reload for new content to get displayed. What to do? I do want the PWA with offline functionality but not with the cost of the site not working when online.
@pwnts
in window.location.reload(true)
the true
is important. It stands for force refresh. If I omit it, things don't work on my side either.
@nibtime
location.reload(true)
is deprecated. See this stackoverflow question.
@ali4heydari
thank you for the info, I did not know that it is deprecated.
However, I think that browsers do not perform the necessary Shift + F5 refresh if the forcedReload
flag is omitted and just do an ordinary F5 reload instead. A F5 reload does not solve the white page errors of gatsby-plugin-offline
.
When calling window.location.reload()
without any parameter, there can only be one kind of behavior, so it is either F5 or Shift + F5. The decision to ignore (not just deprecate) the forceReload
flag in the future would effectively rule out the possibility to programmatically trigger a Shift + F5 refresh in an easy and convenient way, assuming browsers would consistently perform F5 behavior on parameterless window.location.reload()
. Inconsistent behavior, i.e. every browser comes with its very own interpretation of window.location.reload()
would be a nightmare and actually make the function itself unusable.
Removing the forcedReload
feature would be too bad, since those kinds of refreshes are a very reliable "last resort" cleanup mechanism, not just for gatsby-plugin-offline
. Browsers might then offer a new explicit function like window.forceReload()
instead, but no such thing exists at the moment. Therefore I can't really understand the reasons for deprecating the forceReload
flag at this point.
This problem is mentioned in an answer to the same stackoverflow question you posted. It suggests an alternative solution involving a POST
request. I am not sure if I like this solution and not sure if this is feasible in a good way with onServiceWorkerUpdateReady
and gatsby-plugin-offline
.
Therefore, I keep using the forcedReload
flag since it's better to be safe than sorry. The force-reload is a hack in the first place to fix problems of gatsby-plugin-offline
that are seriously detrimental to the user experience. Eventually, gatsby-plugin-offline
should solve them so that such hacks are no longer necessary.
Most helpful comment
Hey, @davidbailey00 - Noting that #10432 had been merged I updated all packages and the problem as described in my previous comment no longer exists.
I'll note here, in case somebody else stumbles upon this issue, that this:
should now be:
Works a charm. Thx. :)