JSPM

  • Created
  • Published
  • Downloads 502492
  • Score
    100M100P100Q179923F
  • License MIT

Zero-config PWA for Vite

Package Exports

  • vite-plugin-pwa

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (vite-plugin-pwa) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

vite-plugin-pwa - Zero-config PWA for Vite


Features

  • Generate Service Worker with Offline support (via Workbox)
  • Auto inject Web App Manifest
  • Prompt for new content refreshing
  • Automatic reload when new content available
  • Advanced (injectManifest)
  • Static assets handling

Usage

npm i vite-plugin-pwa -D # yarn add vite-plugin-pwa -D

Add it to vite.config.js

// vite.config.js
import { VitePWA } from 'vite-plugin-pwa'

export default {
  plugins: [
    VitePWA()
  ]
}

Configuration

Simple (generateSW)

VitePWA({
  manifest: {
    // content of manifest
  },
  workbox: {
    // workbox options for generateSW
  }
})

Prompt for new content

Warning: this is the default option when strategies and registerType are not configured. In order for the service worker to be registered, you must invoke the registerSW method from the virtual:pwa-register module.

// main.ts
import { registerSW } from 'virtual:pwa-register'

const updateSW = registerSW({
  onNeedRefresh() {
    // show a prompt to user
  },
  onOfflineReady() {
    // show a ready to work offline to user
  },
})
// when user clicked the "refresh" button
updateSW()
// the page will reload and the up-to-date content will be served.

You can find an example written in Vue 3: ReloadPrompt.vue.

SSR/SSG

If you are using SSR/SSG, you need to import virtual:pwa-register module using dynamic import and checking if window is not undefined:

// pwa.ts
import { registerSW } from 'virtual:pwa-register'
registerSW({ /* options */})

// main.ts
if (typeof window !== 'undefined') {
    import('./pwa')
}

Automatic reload when new content available

Warning: in order for the service worker to be registered, you must invoke the registerSW method from the virtual:pwa-register module.

With this option, once the service worker detects new content available, then it will update caches and will reload all browser windows/tabs with the application opened automatically to take the control.

The disadvantage of using this option is that the user can lose data in other browser windows / tabs in which the application is open and is filling in a form.

If your application has forms, it is recommended that you change the behavior to use default prompt option to allow the user decide when to update the content of the application.

Configuration

With this option, the plugin will force workbox.clientsClaim and workbox.skipWaiting to true.

VitePWA({
  registerType: 'autoUpdate',  
  manifest: {
    // content of manifest
  },
  workbox: {
    // workbox options for generateSW
  }
})

Runtime

// main.ts
import { registerSW } from 'virtual:pwa-register'

const updateSW = registerSW({
  onOfflineReady() {
    // show a ready to work offline to user
  },
})

SSR/SSG

If you are using SSR/SSG, you need to import virtual:pwa-register module using dynamic import and checking if window is not undefined:

// pwa.ts
import { registerSW } from 'virtual:pwa-register'
registerSW({ /* options */})

// main.ts
if (typeof window !== 'undefined') {
    import('./pwa')
}

Advanced (injectManifest)

You will need to include workbox-* dependencies as dev dependencies.

// sw.js
import { precacheAndRoute } from 'workbox-precaching'
// self.__WB_MANIFEST is default injection point
precacheAndRoute(self.__WB_MANIFEST)
// vite.config.js
VitePWA({
  strategies: 'injectManifest',
  manifest: {
    // content of manifest
  }
})

If you need your custom service worker works with Prompt for new content behavior, you need to include on it at least this code (see also this example: sw.ts):

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING')
    self.skipWaiting()
})

You can use Typescript to build your service worker, you can find an example written for a Vue 3 project: sw.ts. To resolve service worker types, just add WebWorker to lib entry on your tsconfig.json file, for example:

"lib": ["ESNext", "DOM", "WebWorker"],

Static assets handling

By default, all icons on PWA Manifest option found under Vite's publicDir option directory, will be included in the service worker precache. You can disable this option using includeManifestIcons: false.

You can also add another static assets such as favicon, svg and font files using includeAssets option. The includeAssets option will be resolved using fast-glob found under Vite's publicDir option directory, and so you can use regular expressions to include those assets, for example: includeAssets: ['fonts/*.ttf', 'images/*.png']. You don't need to configure PWA Manifest icons on includeAssets option.

You can find an example written for a Vue 3 here.

If you need to include other assets that are not under Vite's publicDir option directory, you can use the globPatterns parameter of workbox or injectManifest plugin options:

VitePWA({
  workbox: {
    globPatterns: [],
    // ...
  },
  // or for injectManifest strategy
  injectManifest: {
    globPatterns: [],
    // ...
  }  
})

Configure application to check for Service Worker updates

As explained in Manual Updates entry on The Service Worker Lifecycle here, you can use this code to configure this behavior on your application:

// main.ts
import { registerSW } from 'virtual:pwa-register'

const updateSW = registerSW({
  // other options
  onRegistered(r) {
    r && setInterval(() => {
      r.update()
    }, 60 * 60 * 1000 /* 1 hour: timeout in milliseconds */)
  }
})

Warning: since workbox-window uses a time-based heuristic algorithm to handle service worker updates, if you build your service worker and register it again, if the time between last registration and the new one is less than 1 minute, then, workbox-window will handle the service worker update found event as an external event, and so the behavior could be strange (for example, if using prompt, instead showing the dialog for new content available, the ready to work offline dialog will be shown; if using autoUpdate, the ready to work offline dialog will be shown and shouldn't be shown).

Full config

Check out the type declaration src/types.ts and the following links for more details.

IDE errors 'Cannot find module' (ts2307)

If your TypeScript build step or IDE complain about not being able to find modules or type definitions on imports, add the following to the compilerOptions.types array of your tsconfig.json:

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "vite-plugin-pwa/client"
    ]
  }
}

Testing service worker

Since this plugin will not generate the service worker on development, you can test it on local following these steps:

  1. add serve script to your package.json if not before:
"serve": "vite preview"
  1. build your app and run serve: npm run build && npm run serve.

Sponsors

This project is part of my Sponsor Program

License

MIT License © 2020 Anthony Fu