Update Prompt UI
The prompt registration strategy
Section titled “The prompt registration strategy”When registerType is set to 'prompt', vite-plugin-pwa does NOT call skipWaiting() automatically. Instead it provides the useRegisterSW() hook from the virtual:pwa-register/react virtual module so you can build your own update UI. This gives users control over when the new service worker activates and the page reloads.
The useRegisterSW hook
Section titled “The useRegisterSW hook”Import the hook from the virtual module that vite-plugin-pwa exposes at build time:
import { useRegisterSW } from 'virtual:pwa-register/react';The hook returns three values:
needRefresh— a[boolean, setter]tuple. The boolean istruewhen a new service worker has installed and is waiting to activate.offlineReady— a[boolean, setter]tuple. The boolean istruewhen the app’s assets are fully cached and the app can run offline.updateServiceWorker(reloadPage?: boolean)— call this withtrueto sendskipWaiting()to the waiting service worker and reload the page.
ReloadPrompt component
Section titled “ReloadPrompt component”The component below reads those three values and renders a toast banner only when there is something to tell the user.
import { useRegisterSW } from 'virtual:pwa-register/react';
export function ReloadPrompt() { const { offlineReady: [offlineReady, setOfflineReady], needRefresh: [needRefresh, setNeedRefresh], updateServiceWorker, } = useRegisterSW();
if (!offlineReady && !needRefresh) { return null; }
return ( <div style={{ position: 'fixed', bottom: '1rem', right: '1rem', padding: '1rem', background: '#1e1e2e', color: '#cdd6f4', borderRadius: '0.5rem', boxShadow: '0 2px 8px rgba(0,0,0,0.4)', zIndex: 9999, }} > {offlineReady ? ( <p>App ready to work offline.</p> ) : ( <p>New content available, click Reload to update.</p> )}
{needRefresh && ( <button onClick={() => updateServiceWorker(true)}>Reload</button> )}
<button onClick={() => { setOfflineReady(false); setNeedRefresh(false); }} > Close </button> </div> );}Wiring it up
Section titled “Wiring it up”Import ReloadPrompt in your App.tsx and render it at the bottom of the component tree so it floats above all other content:
import { ReloadPrompt } from './ReloadPrompt';
export default function App() { return ( <> {/* your app content */} <ReloadPrompt /> </> );}TypeScript type shim
Section titled “TypeScript type shim”If TypeScript reports that it cannot find the module virtual:pwa-register/react, add a triple-slash reference to the vite-plugin-pwa client types at the top of your vite-env.d.ts (or any .d.ts file in your project):
/// <reference types="vite-plugin-pwa/client" />This tells TypeScript about the virtual module declarations that vite-plugin-pwa ships, resolving the import error without any additional package installation.