# Astro SW [![Package information: NPM version](https://img.shields.io/npm/v/@ayco/astro-sw)](https://www.npmjs.com/package/@ayco/astro-sw) [![Package information: NPM license](https://img.shields.io/npm/l/@ayco/astro-sw)](https://www.npmjs.com/package/@ayco/astro-sw) Use your own authored [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) with Astro. The integration accepts the path to your service worker and automatically injects dynamic variables such as `__assets` generated by Astro for caching. It works on all Astro output options: `static`, `server`, or `hybrid`, and lets developers retain the flexibility for various [caching strategies](https://developer.chrome.com/docs/workbox/caching-strategies-overview/). ## Installation In your [Astro](https://astro.build) project: ```bash # if using npm $ npm i -D @ayco/astro-sw # if using pnpm $ pnpm add -D @ayco/astro-sw ``` ## Minimal Usage Here's an example `astro.config.mjs` file: ```js import { defineConfig } from "astro/config"; import serviceWorker from "@ayco/astro-sw"; export default defineConfig({ integrations: [ serviceWorker({ path: "./src/sw.ts", }), ], }); ``` For more options available, see the [API](#api). ## TypeScript support We use `esbuild` to resolve service worker `imports` and build TS files! You can customize the build options by providing it to the `esbuild` configuration property. ```js import { defineConfig } from "astro/config"; import serviceWorker from "@ayco/astro-sw"; export default defineConfig({ integrations: [ serviceWorker({ path: "./src/sw.ts", esbuild: { minify: true, }, }), ], }); ``` ## Injected variables The most important variable your service worker will have access to is `__assets`, which contains all routes and public assets that Astro includes in your build. Additionally, you will also get `__prefix` and `__version` you can use for naming & invalidating your Cache storage (useful for debugging purposes). ## eslint globals Because of the injected variables not being defined in your script, you might get `eslint` errors for the undefined variables when you have the `no-undef` rule. You can use our exported `globals` object in your eslint config as follows: ```js import astroSwGlobals from "@ayco/astro-sw/globals"; export default [ { languageOptions: { globals: { ...astroSwGlobals, }, }, }, // add more generic rule sets here, such as: // jsPlugin.configs.recommended, ]; ``` ## Registration Hooks Hooks are provided for adding custom logic that triggers in various service worker registration events. The following properties are available for the `registrationHooks` configuration: 1. `installing` - when the registration is 'installing' 1. `waiting` - when the registration is 'waiting' 1. `active` - when the registration is 'active' 1. `error` - when the registration throws an error 1. `unsupported` - when the service workers are unsupported 1. `afterRegistration` - after the registration succeeds ```js import { defineConfig } from "astro/config"; import serviceWorker from "@ayco/astro-sw"; export default defineConfig({ integrations: [ serviceWorker({ path: "./src/sw.ts", registrationHooks: { afterRegistration: async () => { const sw = await navigator.serviceWorker.getRegistration(); console.log(">>> registrered", sw); }, installing: () => console.log("installing..."), waiting: () => console.log("waiting..."), active: () => console.log("active..."), error: (error) => console.error(error), unsupported: () => console.log(":("), }, }), ], }); ``` ## API The integration accepts a configuration object with the following properties | property | type | required? | notes | | ------------------- | ---------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | path | string | required | path to your _own_ service worker script; no surprises & easy debugging | | assetCachePrefix | string | optional | cache storage name prefix | | assetCacheVersionID | string | optional | cache storage name versioning; by default, a random UUID is used | | customRoutes | string[] | optional | list of custom routes you want to be cached. Beware that non-existent routes that result to HTTP Error404 will cause the service worker to fail | | excludeRoutes | string[] | optional | list of routes you want to be ignored/removed from assets | | logAssets | boolean | optional | set to see a list of the assets found; defaults to false | | esbuild | [BuildOptions](https://esbuild.github.io/api/) | optional | custom build options for your service worker script | | registrationHooks | object | optional | provide callbacks for various registration events; see section on [Registration Hooks](#registration-hooks) | ## Background This integration was developed to support the Caching strategy needs of [Cozy](https://cozy.ayco.io) -- the modern reading companion for the Web. You can find [an example service worker in the repository](https://github.com/ayoayco/Cozy/blob/main/src/sw.mjs).