How do I implement a typescript service worker with vite-plugin-pwa in Vue 3
Asked Answered
T

1

11

I want to make a single-page application available for offline. So I want to use a PWA Service Worker in my Vue webapp and use typescript and workbox for it. I followed the examples from https://vite-plugin-pwa.netlify.app/guide/inject-manifest.html#typescript-support.

When building the typescript I get many TS2403 errors like:

node_modules/typescript/lib/lib.webworker.d.ts:5720:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onoffline' must be of type '((this: Window, ev: Event) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null'.
// ...
Found 21 errors in 2 files.

Errors  Files
     3  node_modules/typescript/lib/lib.dom.d.ts:25
    18  node_modules/typescript/lib/lib.webworker.d.ts:25
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] build: `vue-tsc --noEmit && vite build`
npm ERR! Exit status 2

Here are the steps I did.

The first thing I did was to install the Vite plugin:

npm i vite-plugin-pwa -D

then to the vite.config.ts I added the

import { VitePWA } from "vite-plugin-pwa";
//...
VitePWA({
    strategies: 'generateSW', // default
    includeAssets: [ "favicon.svg", /* ... */ ],
    manifest: {
      name: "Name of your app", 
      // ...
    },
}),
// ...

First build here was working fine, but with the next steps I get the error.

Now in the vite.config.ts I added the config for using a typescript

VitePWA({
    srcDir: 'src',
    filename: 'sw.ts',
    workbox: { 
        swDest: "sw.js"
    },
    strategies: 'injectManifest', // changed
    // ...

then changed the tsconfig.json (added WebWorker to lib and added types):

//"lib": ["esnext", "dom" ], // before
"lib": ["esnext", "dom", "WebWorker"],
"types": ["vite-plugin-pwa/client"]

and finally added the sw.ts in the src folder:

/// <reference lib="WebWorker" />
import { skipWaiting, clientsClaim } from "workbox-core"
import { precacheAndRoute } from "workbox-precaching";

declare const self: ServiceWorkerGlobalScope

precacheAndRoute(self.__WB_MANIFEST);
skipWaiting();
clientsClaim();
Trixi answered 17/3, 2022 at 19:11 Comment(1)
see also msw in browser doesn't work with Vite and msw-ts-vitejsEfficacious
E
3

I would recommend removing "WebWorker" from your tsconfig.json's lib property, and just use the /// <reference lib="webworker" /> triple-slash directive to add the lib reference at the top of your sw.ts file.

You can see an example project with this setup if it helps.

Ericaericaceous answered 17/3, 2022 at 20:11 Comment(2)
Thanks for the tip with the example project. Removing the "WebWorker" from the lib was half the way. To resolve the problem I had to add "exclude": ["src/sw.ts"], in tsconfig.json. Isn't this bad practice to exclude the file? Then I'm able to write code that is not type safe.Trixi
You can isolate the ServiceWorker code which shouldn't have any connection to your main site code beyond importing shared/common libraries. This can be done with a tsconfig.sw.json that's only for the Service Worker logic.Lizzielizzy

© 2022 - 2024 — McMap. All rights reserved.