---
url: /guide/build-sw.md
---

# Advanced (buildSW)

With this service worker `strategy` you can build your own service worker.

The `@unplugin-pwa/vite` plugin will compile your custom service worker and inject its service worker's precache manifest.

If your service worker is located at `public` folder, `buildSW` will fail, you should use `injectManifest` instead.

If you want to change the location and/or the service worker name, you will need to change the following plugin options:

* `buildSW.swSrc`: **must** be relative to the project root folder
* `filename`: if you want to change the service worker name on build.

For example, if your service worker is located at `/src/my-sw.js` you must configure it using:

```ts
import { VitePWA } from '@unplugin-pwa/vite'

export default defineConfig({
  plugins: [
    VitePWA({
      strategies: 'buildSW',
      buildSW: {
	    swSrc: 'src/my-sw.js',
      }
    })
  ]
})
```

## Custom Service worker

We recommend you to use [Vite PWA Workbox](https://developer.chrome.com/docs/workbox/) to build your service worker instead using `importScripts`, you will need to include `@vite-pwa/workbox-swkit` dependency as `dev dependencies` to your project.

### Plugin Configuration

You **must** configure `strategies: 'buildSW'` in `@unplugin-pwa/vite` plugin options in your `vite.config.ts` file:

```ts
VitePWA({
  strategies: 'buildSW',
})
```

### Development

If you would like the service worker to run in development, make sure to enable it in the [devOptions](/guide/development#plugin-configuration) and to set the type to [module](/guide/development#buildsw-strategy) if required.

### Service Worker Code

Your custom service worker (`src/sw.js`) have at least this code (you also need to install `@vite-pwa/workbox-swkit` as `dev dependency` to your project):

```js
import { precacheAndRoute } from '@vite-pwa/workbox-swkit/precaching'

precacheAndRoute(self.__WB_MANIFEST)
```

If you're not using precaching (`self.__WB_MANIFEST`), you need to disable injection point to avoid compilation errors, add the following option to your pwa configuration:

```ts
buildSW: {
  injectionPoint: undefined // null or false
}
```

### Service worker errors on browser

### Cleanup Outdated Caches

### Inject Manifest Source Map&#x20;

### Custom Rollup and Vite Plugins&#x20;

From `v0.18.0`, you can add custom Rollup and/or Vite plugins to the service worker build, using `rollup` and `vite` options in the new `buildPlugins` option.

::: warning
The old `plugins` option has been deprecated, use `buildPlugins.rollup` instead:

* if `buildPlugins.rollup` is configured then `plugins` will be ignored
* if `buildPlugins.rollup` is not configured then `plugins` will be used
  :::

You can check the [vue-router example](https://github.com/vite-pwa/vite-plugin-pwa/tree/main/examples/vue-router) using a custom Vite plugin with a simple virtual module consumed by both custom service workers.

## Auto Update Behavior

If you need your custom service worker works with `Auto Update` behavior, you need to change the plugin configuration options and add some custom code to your service worker code.

### Plugin Configuration

You must configure `registerType: 'autoUpdate'` to `vite-plugin-pwa` plugin options in your `vite.config.ts` file:

```ts
VitePWA({
  registerType: 'autoUpdate'
})
```

### Service Worker Code

You **must** include in your service worker code at least this code (you also need to install `workbox-core` as `dev dependency` to your project):

```js
import { clientsClaim } from 'workbox-core'

self.skipWaiting()
clientsClaim()
```

## Prompt For Update Behavior

If you need your custom service worker works with `Prompt For Update` behavior, you need to change your service worker code.

### Service Worker Code

You need to include on your service worker at least this code:

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

## TypeScript support

You can use TypeScript to write your custom service worker. To resolve service worker types, just add `WebWorker` to `lib` entry on your `tsconfig.json` file:

```json
{
  "compilerOptions": {
    "lib": ["ESNext", "DOM", "WebWorker"]
  }
}
```

### Plugin Configuration

We recommend you to put your custom service worker inside `src` directory.

You need to configure `srcDir: 'src'` and `filename: 'sw.ts'` plugin options in your `vite.config.ts` file, configure both options with the directory and the name of your custom service worker properly:

```ts
VitePWA({
  srcDir: 'src',
  filename: 'sw.ts'
})
```

### Service Worker Code

You need to define `self` scope with `ServiceWorkerGlobalScope`:

```ts
import { precacheAndRoute } from 'workbox-precaching'

declare let self: ServiceWorkerGlobalScope

precacheAndRoute(self.__WB_MANIFEST)
```
