Skip to content

Adding PWA update prompt in vite react

Posted on:April 8, 2023 at 04:21 PM

Vite react pwa allows a nice and simple way to show a PWA prompt to reload the app and run with latest service worker and assets.

Table of contents

Open Table of contents

PWA Update UI

you might have seen pwa update feature in some apps.

PWA update toast from hoppscotch A screenshot from hoppscotch

Create a simple react pwa with vite

Firstly create a simple react vite app with vite-plugin-pwa.

Create a new component which will be responsible for showing the prompt. Use this component anywhere in the App tree.

import { Button, Group, Modal, Text } from "@mantine/core";
import { showNotification } from "@mantine/notifications";
import { useEffect } from "react";
import { useRegisterSW } from "virtual:pwa-register/react";

const AppUpdateModal = () => {
  const {
    offlineReady: [offlineReady, setOfflineReady],
    needRefresh: [needRefresh, setNeedRefresh],
    updateServiceWorker,
  } = useRegisterSW({
    onRegistered(r) {
      // eslint-disable-next-line prefer-template
      console.log("SW Registered: " + r);
    },
    onRegisterError(error) {
      console.log("SW registration error", error);
    },
  });

  const close = () => {
    setOfflineReady(false);
    setNeedRefresh(false);
  };

  useEffect(() => {
    offlineReady &&
      showNotification({
        title: "Ready",
        message: "App is ready to work offline",
        color: "blue",
      });
  }, [offlineReady]);

  return (
    <>
      <Modal
        opened={needRefresh}
        title="Install update"
        centered
        onClose={close}
      >
        <Text>A new app update is available.</Text>

        <Text c={"dimmed"} fz="xs" mt="sm">
          <strong>Reload</strong> will refresh the app. You may lose the
          progress, if any.
        </Text>
        <Text c={"dimmed"} fz="xs">
          <strong>Cancel</strong> will install the update next time you visit
          the app.
        </Text>

        <Group position="right" mt="lg">
          <Button variant="subtle" onClick={close}>
            Cancel
          </Button>
          <Button onClick={() => updateServiceWorker(true)}>Reload</Button>
        </Group>
      </Modal>
    </>
  );
};

export default AppUpdateModal;

Here we get the state (offlineReady , needRefresh) via useRegisterSW hook from virtual module and based on that we show the modal.

Here I used mantine react UI kit, which is really cool. You may swap with your favourite UI kit.

You will also need to set register type as prompt in vite.config.ts

import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";

export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      registerType: "prompt",
      // other config here ...
    }),
  ],
});

vite-plugin-pwa offers more stategies. You may further explore at https://vite-pwa-org.netlify.app/examples/react.html