如何在gatsby-plugin-offline中监听Service Worker更新事件
Great question! You're right that gatsby-plugin-offline is built on top of offline-plugin, but Gatsby wraps its functionality tightly—so the global event listeners from the offline-plugin docs won't work directly. Here are two reliable ways to detect service worker updates and notify your users in Gatsby:
方法1:使用Gatsby内置的onServiceWorkerUpdateReady钩子(推荐)
Gatsby provides a dedicated browser API hook specifically for this scenario. It triggers automatically when a new service worker is ready to activate, so you don't have to handle low-level service worker events yourself.
- Create or edit the
gatsby-browser.jsfile in your project root (if it doesn't exist, just make a new one). - Add the following code to define the hook and your user notification logic:
exports.onServiceWorkerUpdateReady = () => { const userWantsUpdate = window.confirm( "This app has a new version available! Would you like to refresh to see the latest changes?" ); if (userWantsUpdate) { window.location.reload(); } };
This will prompt users with a browser confirmation dialog when an update is ready, and reload the page if they agree.
方法2:手动监听Service Worker更新事件(自定义控制)
If you need more granular control over the update flow (like custom UI instead of a browser alert), you can directly listen to service worker events in your React components.
For example, add this to a global component like your root Layout.js:
import { useEffect } from 'react'; const Layout = ({ children }) => { useEffect(() => { // Skip if service workers aren't supported if (!navigator.serviceWorker) return; // Wait for the service worker to be ready navigator.serviceWorker.ready.then((registration) => { // Listen for new service worker downloads registration.addEventListener('updatefound', () => { const newWorker = registration.installing; // Track the installation state newWorker.addEventListener('statechange', () => { // When the new worker is installed and the current page is controlled by an old worker if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { // Custom notification logic here console.log('New app version ready!'); // Replace this with your own UI (e.g., a toast or modal) if (confirm('A new version of the app is available. Refresh now?')) { window.location.reload(); } } }); }); }); }, []); return <div className="layout">{children}</div>; }; export default Layout;
Important Notes
- Test in production mode:
gatsby-plugin-offlineonly activates in production (rungatsby build && gatsby serveto test updates locally). - Avoid manual service worker registration: Gatsby handles registration automatically via
gatsby-plugin-offline, so you don't need to callnavigator.serviceWorker.register()yourself unless you've customized the service worker path.
内容的提问来源于stack exchange,提问作者Ilja

