Zero-config PWA plugin for Vite that enables offline functionality, service workers, and web app manifest generation.
—
Framework-specific service worker registration modules that provide seamless integration with React, Vue, Svelte, SolidJS, Preact, and vanilla JavaScript applications.
Basic service worker registration for vanilla JavaScript and non-reactive applications.
// Virtual module: virtual:pwa-register
/**
* Registers the service worker and returns an update function
* @param options - Registration options including callbacks for SW events
* @returns Promise-based function to trigger service worker updates
*/
function registerSW(options?: RegisterSWOptions): (reloadPage?: boolean) => Promise<void>;
interface RegisterSWOptions {
immediate?: boolean;
onNeedRefresh?: () => void;
onOfflineReady?: () => void;
onRegistered?: (registration?: ServiceWorkerRegistration) => void;
onRegisteredSW?: (swScriptUrl: string, registration?: ServiceWorkerRegistration) => void;
onRegisterError?: (error: any) => void;
}Usage Example:
import { registerSW } from "virtual:pwa-register";
const updateSW = registerSW({
immediate: true,
onNeedRefresh() {
if (confirm("New content available. Reload?")) {
updateSW(true);
}
},
onOfflineReady() {
console.log("App ready to work offline");
},
onRegisterError(error) {
console.error("SW registration error", error);
},
});React hook-based service worker registration with state management.
// Virtual module: virtual:pwa-register/react
/**
* React hook for service worker registration with reactive state
* @param options - Registration options
* @returns Object with reactive state and update function
*/
function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: [boolean, Dispatch<SetStateAction<boolean>>];
offlineReady: [boolean, Dispatch<SetStateAction<boolean>>];
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};Usage Example:
import React from "react";
import { useRegisterSW } from "virtual:pwa-register/react";
function PWABadge() {
const {
needRefresh: [needRefresh, setNeedRefresh],
offlineReady: [offlineReady, setOfflineReady],
updateServiceWorker,
} = useRegisterSW({
onRegisteredSW(swUrl, r) {
console.log(`Service Worker at: ${swUrl}`);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
const close = () => {
setOfflineReady(false);
setNeedRefresh(false);
};
return (
<div className="pwa-toast" role="alert">
{(offlineReady || needRefresh) && (
<div className="pwa-message">
{offlineReady ? (
<span>App ready to work offline</span>
) : (
<span>New content available, click to update.</span>
)}
<div>
{needRefresh && (
<button onClick={() => updateSW(true)}>Reload</button>
)}
<button onClick={close}>Close</button>
</div>
</div>
)}
</div>
);
}Vue 3 composable for service worker registration with reactive refs.
// Virtual module: virtual:pwa-register/vue
/**
* Vue composable for service worker registration with reactive state
* @param options - Registration options
* @returns Object with reactive refs and update function
*/
function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: Ref<boolean>;
offlineReady: Ref<boolean>;
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};Usage Example:
<template>
<div v-if="offlineReady || needRefresh" class="pwa-toast" role="alert">
<div class="message">
<span v-if="offlineReady">App ready to work offline</span>
<span v-else>New content available, click to update.</span>
</div>
<div class="buttons">
<button v-if="needRefresh" @click="updateServiceWorker(true)">
Reload
</button>
<button @click="close">Close</button>
</div>
</div>
</template>
<script setup>
import { useRegisterSW } from "virtual:pwa-register/vue";
const { needRefresh, offlineReady, updateServiceWorker } = useRegisterSW({
onRegisteredSW(swUrl, r) {
console.log(`Service Worker at: ${swUrl}`);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
function close() {
offlineReady.value = false;
needRefresh.value = false;
}
</script>Svelte store-based service worker registration with writable stores.
// Virtual module: virtual:pwa-register/svelte
/**
* Svelte store-based service worker registration
* @param options - Registration options
* @returns Object with writable stores and update function
*/
function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: Writable<boolean>;
offlineReady: Writable<boolean>;
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};Usage Example:
<script>
import { useRegisterSW } from "virtual:pwa-register/svelte";
const { needRefresh, offlineReady, updateServiceWorker } = useRegisterSW({
onRegisteredSW(swUrl, r) {
console.log(`Service Worker at: ${swUrl}`);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
function close() {
$offlineReady = false;
$needRefresh = false;
}
</script>
{#if $offlineReady || $needRefresh}
<div class="pwa-toast" role="alert">
<div class="message">
{#if $offlineReady}
<span>App ready to work offline</span>
{:else}
<span>New content available, click to update.</span>
{/if}
</div>
<div class="buttons">
{#if $needRefresh}
<button on:click={() => updateServiceWorker(true)}>Reload</button>
{/if}
<button on:click={close}>Close</button>
</div>
</div>
{/if}SolidJS signal-based service worker registration with accessor/setter pairs.
// Virtual module: virtual:pwa-register/solid
/**
* SolidJS signal-based service worker registration
* @param options - Registration options
* @returns Object with signal accessor/setter pairs and update function
*/
function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: [Accessor<boolean>, Setter<boolean>];
offlineReady: [Accessor<boolean>, Setter<boolean>];
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};Usage Example:
import { Component, Show } from "solid-js";
import { useRegisterSW } from "virtual:pwa-register/solid";
const PWABadge: Component = () => {
const {
needRefresh: [needRefresh, setNeedRefresh],
offlineReady: [offlineReady, setOfflineReady],
updateServiceWorker,
} = useRegisterSW({
onRegisteredSW(swUrl, r) {
console.log(`Service Worker at: ${swUrl}`);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
const close = () => {
setOfflineReady(false);
setNeedRefresh(false);
};
return (
<Show when={offlineReady() || needRefresh()}>
<div class="pwa-toast" role="alert">
<div class="message">
<Show
when={offlineReady()}
fallback={<span>New content available, click to update.</span>}
>
<span>App ready to work offline</span>
</Show>
</div>
<div class="buttons">
<Show when={needRefresh()}>
<button onClick={() => updateServiceWorker(true)}>Reload</button>
</Show>
<button onClick={close}>Close</button>
</div>
</div>
</Show>
);
};Preact hook-based service worker registration with state updaters.
// Virtual module: virtual:pwa-register/preact
/**
* Preact hook for service worker registration with state management
* @param options - Registration options
* @returns Object with state values/updaters and update function
*/
function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: [boolean, StateUpdater<boolean>];
offlineReady: [boolean, StateUpdater<boolean>];
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};Usage Example:
import { h } from "preact";
import { useRegisterSW } from "virtual:pwa-register/preact";
function PWABadge() {
const {
needRefresh: [needRefresh, setNeedRefresh],
offlineReady: [offlineReady, setOfflineReady],
updateServiceWorker,
} = useRegisterSW({
onRegisteredSW(swUrl, r) {
console.log(`Service Worker at: ${swUrl}`);
},
onRegisterError(error) {
console.log("SW registration error", error);
},
});
const close = () => {
setOfflineReady(false);
setNeedRefresh(false);
};
return (
(offlineReady || needRefresh) && (
<div className="pwa-toast" role="alert">
<div className="message">
{offlineReady ? (
<span>App ready to work offline</span>
) : (
<span>New content available, click to update.</span>
)}
</div>
<div className="buttons">
{needRefresh && (
<button onClick={() => updateServiceWorker(true)}>Reload</button>
)}
<button onClick={close}>Close</button>
</div>
</div>
)
);
}Common options available across all framework integrations.
interface RegisterSWOptions {
/** Register service worker immediately on load */
immediate?: boolean;
/** Called when new content is available and user confirmation is needed */
onNeedRefresh?: () => void;
/** Called when app is ready to work offline */
onOfflineReady?: () => void;
/**
* Called after service worker registration (deprecated)
* @deprecated Use onRegisteredSW instead
*/
onRegistered?: (registration?: ServiceWorkerRegistration) => void;
/** Called after service worker registration with SW URL and registration */
onRegisteredSW?: (swScriptUrl: string, registration?: ServiceWorkerRegistration) => void;
/** Called when service worker registration fails */
onRegisterError?: (error: any) => void;
}Function signature for triggering service worker updates across all frameworks.
/**
* Triggers service worker update and page reload
* @param reloadPage - Whether to reload page after update (deprecated parameter)
* @returns Promise that resolves when update is complete
*/
type UpdateServiceWorker = (reloadPage?: boolean) => Promise<void>;Different ways to import virtual modules based on your setup:
// Standard imports
import { registerSW } from "virtual:pwa-register";
import { useRegisterSW } from "virtual:pwa-register/react";
import { useRegisterSW } from "virtual:pwa-register/vue";
// With type imports
import type { RegisterSWOptions } from "virtual:pwa-register";
import type { RegisterSWOptions } from "virtual:pwa-register/react";
// Re-exported from main package
import type { RegisterSWOptions } from "vite-plugin-pwa";Pattern for conditional service worker registration:
import { registerSW } from "virtual:pwa-register";
if ("serviceWorker" in navigator) {
const updateSW = registerSW({
immediate: false,
onNeedRefresh() {
// Show update prompt to user
showUpdatePrompt(() => updateSW(true));
},
onOfflineReady() {
// Notify user app works offline
showOfflineNotification();
},
});
}Install with Tessl CLI
npx tessl i tessl/npm-vite-plugin-pwa