Skip to main content

Service workers

Les service workers agissent comme des serveurs proxy qui gèrent les requêtes réseau au sein de votre application. Cela rend possible le fonctionnement hors-ligne de votre application, mais même si vous n'avez pas besoin de support hors-ligne (ou si vous ne pouvez pas réalistiquement l'implémenter à cause du type d'application que vous développez), il est souvent utile d'utiliser les service workers pour accélérer la navigation en pré-cachant vos JS et CSS compilés.

Dans SvelteKit, si vous avez un fichier src/service-worker.js (ou src/service-worker/index.js), celui-ci sera compilé et automatiquement activé.

Vous pouvez désactiver l'activation automatique si vous avez besoin d'activer le service worker selon votre propre logique ou si vous souhaitez utiliser une autre solution. L'activation par défaut ressemble à quelque chose comme ça :

if ('serviceWorker' in var navigator: Navigator

The Window.navigator read-only property returns a reference to the Navigator object, which has methods and properties about the application running the script.

MDN Reference

navigator
) {
function addEventListener<"load">(type: "load", listener: (this: Window, ev: Event) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)addEventListener('load', function () { var navigator: Navigator

The Window.navigator read-only property returns a reference to the Navigator object, which has methods and properties about the application running the script.

MDN Reference

navigator
.Navigator.serviceWorker: ServiceWorkerContainer

The serviceWorker read-only property of the Navigator interface returns the ServiceWorkerContainer object for the associated document, which provides access to registration, removal, upgrade, and communication with the ServiceWorker. Available only in secure contexts.

MDN Reference

serviceWorker
.ServiceWorkerContainer.register(scriptURL: string | URL, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>

The register() method of the ServiceWorkerContainer interface creates or updates a ServiceWorkerRegistration for the given scope.

MDN Reference

register
('./path/to/service-worker.js');
}); }

Au sein du service worker

Au sein du service worker vous avez accès au module $service-worker, qui vous fournit les chemins vers tous les assets statiques, fichiers compilés et pages prérendues. Vous avez également accès à la chaîne de caractères représentant la version de l'application, que vous pouvez utiliser pour créer un nom de cache unique, ainsi qu'à la base du chemin de déploiement. Si votre configuration Vite précise l'option define (utilisé pour le remplacement de variables globales), celle-ci sera appliquée aux service workers ainsi qu'à vos fichiers compilés de serveur et de client.

L'exemple suivant met en cache l'application compilée et tout fichier dans le dossier static de manière agressive, et met en cache toute autre requête lorsqu'elles se produisent. Ceci rend de facto toute page visitée disponible en mode hors-ligne.

src/service-worker
// Désactive l'accès au types du DOM comme `HTMLElement` qui ne sont pas disponibles
// dans un service worker et instancie les variables globales pertinentes
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="webworker" />

// Assure que l'import de `$service-worker` soit correctement typé
/// <reference types="@sveltejs/kit" />

// Uniquement nécessaire si vous avez un import depuis `$env/static/public`
/// <reference types="../.svelte-kit/ambient.d.ts" />

import { const build: string[]

An array of URL strings representing the files generated by Vite, suitable for caching with cache.addAll(build). During development, this is an empty array.

build
, const files: string[]

An array of URL strings representing the files in your static directory, or whatever directory is specified by config.kit.files.assets. You can customize which files are included from static directory using config.kit.serviceWorker.files

files
, const version: string

See config.kit.version. It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.

version
} from '$service-worker';
// Ceci donne à `self` le typage correct const const self: Window & typeof globalThisself = /** @type {ServiceWorkerGlobalScope} */ (/** @type {unknown} */ (module globalThisglobalThis.var self: Window & typeof globalThis

The Window.self read-only property returns the window itself, as a WindowProxy.

MDN Reference

self
));
// Crée un nom de cache unique pour ce déploiement const const CACHE: stringCACHE = `cache-${const version: string

See config.kit.version. It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.

version
}`;
const const ASSETS: string[]ASSETS = [ ...const build: string[]

An array of URL strings representing the files generated by Vite, suitable for caching with cache.addAll(build). During development, this is an empty array.

build
, // l'application elle-même
...const files: string[]

An array of URL strings representing the files in your static directory, or whatever directory is specified by config.kit.files.assets. You can customize which files are included from static directory using config.kit.serviceWorker.files

files
// tout ce qui est dans `static`
]; const self: Window & typeof globalThisself.function addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

addEventListener
('install', (event: Eventevent) => {
// Create a new cache and add all files to it // Crée un nouveau cache et y ajoute tous les fichiers async function function (local function) addFilesToCache(): Promise<void>addFilesToCache() { const const cache: Cachecache = await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.open(cacheName: string): Promise<Cache>

The open() method of the the Cache object matching the cacheName.

MDN Reference

open
(const CACHE: stringCACHE);
await const cache: Cachecache.Cache.addAll(requests: Iterable<RequestInfo>): Promise<void> (+1 overload)

The addAll() method of the Cache interface takes an array of URLs, retrieves them, and adds the resulting response objects to the given cache.

MDN Reference

addAll
(const ASSETS: string[]ASSETS);
} event: Eventevent.waitUntil(function (local function) addFilesToCache(): Promise<void>addFilesToCache()); }); const self: Window & typeof globalThisself.function addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

addEventListener
('activate', (event: Eventevent) => {
// Supprime du disque les données précédemment mises en cache async function function (local function) deleteOldCaches(): Promise<void>deleteOldCaches() { for (const const key: stringkey of await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.keys(): Promise<string[]>

The keys() method of the CacheStorage interface returns a Promise that will resolve with an array containing strings corresponding to all of the named Cache objects tracked by the CacheStorage object in the order they were created.

MDN Reference

keys
()) {
if (const key: stringkey !== const CACHE: stringCACHE) await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.delete(cacheName: string): Promise<boolean>

The delete() method of the CacheStorage interface finds the Cache object matching the cacheName, and if found, deletes the Cache object and returns a Promise that resolves to true.

MDN Reference

delete
(const key: stringkey);
} } event: Eventevent.waitUntil(function (local function) deleteOldCaches(): Promise<void>deleteOldCaches()); }); const self: Window & typeof globalThisself.function addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

addEventListener
('fetch', (event: Eventevent) => {
// ignore les requêtes POST, etc if (event: Eventevent.request.method !== 'GET') return; async function function (local function) respond(): Promise<Response>respond() { const const url: URLurl = new var URL: new (url: string | URL, base?: string | URL) => URL

The URL interface is used to parse, construct, normalize, and encode URL.

MDN Reference

URL class is a global reference for import { URL } from 'node:url' https://nodejs.org/api/url.html#the-whatwg-url-api

@sincev10.0.0
URL
(event: Eventevent.request.url);
const const cache: Cachecache = await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.open(cacheName: string): Promise<Cache>

The open() method of the the Cache object matching the cacheName.

MDN Reference

open
(const CACHE: stringCACHE);
// les fichiers `build`/`files` peuvent toujours être servis depuis le cache if (const ASSETS: string[]ASSETS.Array<string>.includes(searchElement: string, fromIndex?: number): boolean

Determines whether an array includes a certain element, returning true or false as appropriate.

@paramsearchElement The element to search for.
@paramfromIndex The position in this array at which to begin searching for searchElement.
includes
(const url: URLurl.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure.

MDN Reference

pathname
)) {
const const response: Response | undefinedresponse = await const cache: Cachecache.Cache.match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>

The match() method of the Cache interface returns a Promise that resolves to the Response associated with the first matching request in the Cache object.

MDN Reference

match
(const url: URLurl.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure.

MDN Reference

pathname
);
if (const response: Response | undefinedresponse) { return const response: Responseresponse; } } // pour tout le reste, essayer d'abord le réseau, mais // se reporter au cache si le réseau est indisponible try { const const response: Responseresponse = await function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)fetch(event: Eventevent.request); // si nous sommes hors-ligne, fetch peut renvoyer une valeur qui n'est pas une Response // plutôt que de lever une erreur — and nous ne pouvons pas passer cette non-Response à // respondWith if (!(const response: Responseresponse instanceof
var Response: {
    new (body?: BodyInit | null, init?: ResponseInit): Response;
    prototype: Response;
    error(): Response;
    json(data: any, init?: ResponseInit): Response;
    redirect(url: string | URL, status?: number): Response;
}

The Response interface of the Fetch API represents the response to a request.

MDN Reference

Response
)) {
throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('la réponse de fetch est invalide');
} if (const response: Responseresponse.Response.status: number

The status read-only property of the Response interface contains the HTTP status codes of the response.

MDN Reference

status
=== 200) {
const cache: Cachecache.Cache.put(request: RequestInfo | URL, response: Response): Promise<void>

The put() method of the Often, you will just want to Window/fetch one or more requests, then add the result straight to your cache.

MDN Reference

put
(event: Eventevent.request, const response: Responseresponse.Response.clone(): Response

The clone() method of the Response interface creates a clone of a response object, identical in every way, but stored in a different variable.

MDN Reference

clone
());
} return const response: Responseresponse; } catch (function (local var) err: unknownerr) { const const response: Response | undefinedresponse = await const cache: Cachecache.Cache.match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>

The match() method of the Cache interface returns a Promise that resolves to the Response associated with the first matching request in the Cache object.

MDN Reference

match
(event: Eventevent.request);
if (const response: Response | undefinedresponse) { return const response: Responseresponse; } // s'il n'y a pas de cache, lever une erreur // puisqu'il n'y a rien à répondre à cette requête throw function (local var) err: unknownerr; } } event: Eventevent.respondWith(function (local function) respond(): Promise<Response>respond()); });
// Désactive l'accès au types du DOM comme `HTMLElement` qui ne sont pas disponibles
// dans un service worker et instancie les variables globales pertinentes
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="webworker" />

// Assure que l'import de `$service-worker` soit correctement typé
/// <reference types="@sveltejs/kit" />

// Uniquement nécessaire si vous avez un import depuis `$env/static/public`
/// <reference types="../.svelte-kit/ambient.d.ts" />

import { const build: string[]

An array of URL strings representing the files generated by Vite, suitable for caching with cache.addAll(build). During development, this is an empty array.

build
, const files: string[]

An array of URL strings representing the files in your static directory, or whatever directory is specified by config.kit.files.assets. You can customize which files are included from static directory using config.kit.serviceWorker.files

files
, const version: string

See config.kit.version. It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.

version
} from '$service-worker';
// Ceci donne à `self` le typage correct const const self: ServiceWorkerGlobalScopeself = module globalThisglobalThis.var self: Window & typeof globalThis

The Window.self read-only property returns the window itself, as a WindowProxy.

MDN Reference

self
as unknown as type ServiceWorkerGlobalScope = /*unresolved*/ anyServiceWorkerGlobalScope;
// Crée un nom de cache unique pour ce déploiement const const CACHE: stringCACHE = `cache-${const version: string

See config.kit.version. It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches.

version
}`;
const const ASSETS: string[]ASSETS = [ ...const build: string[]

An array of URL strings representing the files generated by Vite, suitable for caching with cache.addAll(build). During development, this is an empty array.

build
, // l'application elle-même
...const files: string[]

An array of URL strings representing the files in your static directory, or whatever directory is specified by config.kit.files.assets. You can customize which files are included from static directory using config.kit.serviceWorker.files

files
// tout ce qui est dans `static`
]; const self: ServiceWorkerGlobalScopeself.addEventListener('install', (event: anyevent) => { // Create a new cache and add all files to it // Crée un nouveau cache et y ajoute tous les fichiers async function function (local function) addFilesToCache(): Promise<void>addFilesToCache() { const const cache: Cachecache = await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.open(cacheName: string): Promise<Cache>

The open() method of the the Cache object matching the cacheName.

MDN Reference

open
(const CACHE: stringCACHE);
await const cache: Cachecache.Cache.addAll(requests: Iterable<RequestInfo>): Promise<void> (+1 overload)

The addAll() method of the Cache interface takes an array of URLs, retrieves them, and adds the resulting response objects to the given cache.

MDN Reference

addAll
(const ASSETS: string[]ASSETS);
} event: anyevent.waitUntil(function (local function) addFilesToCache(): Promise<void>addFilesToCache()); }); const self: ServiceWorkerGlobalScopeself.addEventListener('activate', (event: anyevent) => { // Supprime du disque les données précédemment mises en cache async function function (local function) deleteOldCaches(): Promise<void>deleteOldCaches() { for (const const key: stringkey of await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.keys(): Promise<string[]>

The keys() method of the CacheStorage interface returns a Promise that will resolve with an array containing strings corresponding to all of the named Cache objects tracked by the CacheStorage object in the order they were created.

MDN Reference

keys
()) {
if (const key: stringkey !== const CACHE: stringCACHE) await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.delete(cacheName: string): Promise<boolean>

The delete() method of the CacheStorage interface finds the Cache object matching the cacheName, and if found, deletes the Cache object and returns a Promise that resolves to true.

MDN Reference

delete
(const key: stringkey);
} } event: anyevent.waitUntil(function (local function) deleteOldCaches(): Promise<void>deleteOldCaches()); }); const self: ServiceWorkerGlobalScopeself.addEventListener('fetch', (event: anyevent) => { // ignore les requêtes POST, etc if (event: anyevent.request.method !== 'GET') return; async function function (local function) respond(): Promise<Response>respond() { const const url: URLurl = new var URL: new (url: string | URL, base?: string | URL) => URL

The URL interface is used to parse, construct, normalize, and encode URL.

MDN Reference

URL class is a global reference for import { URL } from 'node:url' https://nodejs.org/api/url.html#the-whatwg-url-api

@sincev10.0.0
URL
(event: anyevent.request.url);
const const cache: Cachecache = await var caches: CacheStorage

Available only in secure contexts.

MDN Reference

caches
.CacheStorage.open(cacheName: string): Promise<Cache>

The open() method of the the Cache object matching the cacheName.

MDN Reference

open
(const CACHE: stringCACHE);
// les fichiers `build`/`files` peuvent toujours être servis depuis le cache if (const ASSETS: string[]ASSETS.Array<string>.includes(searchElement: string, fromIndex?: number): boolean

Determines whether an array includes a certain element, returning true or false as appropriate.

@paramsearchElement The element to search for.
@paramfromIndex The position in this array at which to begin searching for searchElement.
includes
(const url: URLurl.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure.

MDN Reference

pathname
)) {
const const response: Response | undefinedresponse = await const cache: Cachecache.Cache.match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>

The match() method of the Cache interface returns a Promise that resolves to the Response associated with the first matching request in the Cache object.

MDN Reference

match
(const url: URLurl.URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure.

MDN Reference

pathname
);
if (const response: Response | undefinedresponse) { return const response: Responseresponse; } } // pour tout le reste, essayer d'abord le réseau, mais // se reporter au cache si le réseau est indisponible try { const const response: Responseresponse = await function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)fetch(event: anyevent.request); // si nous sommes hors-ligne, fetch peut renvoyer une valeur qui n'est pas une Response // plutôt que de lever une erreur — and nous ne pouvons pas passer cette non-Response à // respondWith if (!(const response: Responseresponse instanceof
var Response: {
    new (body?: BodyInit | null, init?: ResponseInit): Response;
    prototype: Response;
    error(): Response;
    json(data: any, init?: ResponseInit): Response;
    redirect(url: string | URL, status?: number): Response;
}

The Response interface of the Fetch API represents the response to a request.

MDN Reference

Response
)) {
throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('la réponse de fetch est invalide');
} if (const response: Responseresponse.Response.status: number

The status read-only property of the Response interface contains the HTTP status codes of the response.

MDN Reference

status
=== 200) {
const cache: Cachecache.Cache.put(request: RequestInfo | URL, response: Response): Promise<void>

The put() method of the Often, you will just want to Window/fetch one or more requests, then add the result straight to your cache.

MDN Reference

put
(event: anyevent.request, const response: Responseresponse.Response.clone(): Response

The clone() method of the Response interface creates a clone of a response object, identical in every way, but stored in a different variable.

MDN Reference

clone
());
} return const response: Responseresponse; } catch (function (local var) err: unknownerr) { const const response: Response | undefinedresponse = await const cache: Cachecache.Cache.match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>

The match() method of the Cache interface returns a Promise that resolves to the Response associated with the first matching request in the Cache object.

MDN Reference

match
(event: anyevent.request);
if (const response: Response | undefinedresponse) { return const response: Responseresponse; } // s'il n'y a pas de cache, lever une erreur // puisqu'il n'y a rien à répondre à cette requête throw function (local var) err: unknownerr; } } event: anyevent.respondWith(function (local function) respond(): Promise<Response>respond()); });

Faites attention lorsque vous mettez des choses en cache ! Dans certains cas, des données périmées peuvent être pires que pas de données du tout en mode hors-ligne. Puisque les navigateurs vont vider le cache s'il remplit trop, vous devriez également faire attention lorsque vous mettez en cache des assets de grande taille comme des fichiers vidéo.

Lors du développement

Le service worker est compilé pour la production, mais pas lors du développement. Pour cette raison, seuls les navigateurs supportant les modules au sein des service workers seront capables de les utiliser lors du développement. Si vous activez manuellement votre service worker, vous aurez besoin de fournir l'option { type: 'module' } en mode développement :

import { const dev: boolean

Whether the dev server is running. This is not guaranteed to correspond to NODE_ENV or MODE.

dev
} from '$app/environment';
var navigator: Navigator

The Window.navigator read-only property returns a reference to the Navigator object, which has methods and properties about the application running the script.

MDN Reference

navigator
.Navigator.serviceWorker: ServiceWorkerContainer

The serviceWorker read-only property of the Navigator interface returns the ServiceWorkerContainer object for the associated document, which provides access to registration, removal, upgrade, and communication with the ServiceWorker. Available only in secure contexts.

MDN Reference

serviceWorker
.ServiceWorkerContainer.register(scriptURL: string | URL, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>

The register() method of the ServiceWorkerContainer interface creates or updates a ServiceWorkerRegistration for the given scope.

MDN Reference

register
('/service-worker.js', {
RegistrationOptions.type?: WorkerType | undefinedtype: const dev: boolean

Whether the dev server is running. This is not guaranteed to correspond to NODE_ENV or MODE.

dev
? 'module' : 'classic'
});

build et prerendered sont des tableaux vides lors du développement.

Autres solutions

L'implémentation du service worker de SvelteKit est conçue pour être simple d'usage et est probablement une bonne solution pour la plupart des gens. Cependant, en dehors de SvelteKit, beaucoup d'applications PWA utilisent la librairie Workbox. Si vous êtes habitué•e à cette librairie, vous pourriez préférer l'usage du plugin PWA de Vite.

Références

Pour plus d'informations sur les service workers de manière générale, nous recommandons la documentation de MDN.

Modifier cette page sur Github llms.txt

précédent suivant