Utiliser Workbox sans la mise en cache préalable

Jusqu'à présent, cette documentation a été fortement axée sur la mise en cache précoce, et a souvent abordé les outils de compilation generateSW et injectManifest. Bien qu'il existe de nombreuses bonnes raisons d'inclure une logique de mise en cache préalable dans votre service worker, vous n'avez pas besoin d'utiliser la mise en cache préalable pour utiliser Workbox.

Peut-être que votre projet n'a besoin que de la mise en cache de l'environnement d'exécution, ou peut-être souhaitez-vous trouver un moyen plus propre d'intégrer des API de service worker, comme les flux Web push. Il s'agit de cas dans lesquels vous ne souhaitez pas utiliser les outils de compilation de Workbox, et c'est ce que nous allons aborder dans cet article.

Lors de l'utilisation d'un bundler

Les bundlers jouent un rôle important dans l'environnement du développement Web, et il est fort probable que votre projet en utilise un. Si tel est le cas, sachez que vous n'avez pas besoin d'utiliser un plug-in bundler (comme workbox-webpack-plugin) si vous ne mettez rien en cache. Vous allez considérer votre service worker comme un point d'entrée distinct dans votre application.

À la racine du répertoire source de votre projet, créez un service worker et utilisez tous les modules Workbox requis par votre application. Voici un exemple sans mise en cache préalable, qui configure des stratégies de mise en cache pour les demandes de composants de navigation et d'image dans des instances Cache distinctes:

// sw.js
import {NetworkFirst, CacheFirst} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';

const navigationRoute = new NavigationRoute(new NetworkFirst({
  cacheName: 'navigations'
}));

const imageAssetRoute = new Route(({request}) => {
  return request.destination === 'image';
}, new CacheFirst({
  cacheName: 'image-assets'
}));

registerRoute(navigationRoute);
registerRoute(imageAssetRoute);

Il suffit ensuite de spécifier ce service worker comme point d'entrée dans le bundler de votre choix. Voici quelques exemples de méthodes pour y parvenir avec quelques bundles populaires.

pack Web

webpack accepte les points d'entrée dans sa configuration entry. Voici quelques points à prendre en compte lorsque vous utilisez cette approche:

  1. Pour vous assurer que votre service worker dispose du champ d'application le plus large possible, vous devez envoyer la sortie à la racine de votre répertoire de sortie.
  2. Vous ne voulez pas que le service worker soit géré par version, car ses mises à jour génèrent de nouveaux hachages qui peuvent entraîner le déploiement de plusieurs service workers sur votre site Web.

Pour remplir les conditions ci-dessus, une fonction peut être transmise à output.filename pour vérifier si le point d'entrée en cours de traitement est bien celui du service worker. Sinon, les fichiers avec versions gérées sont écrits dans leurs destinations normales.

// webpack.config.js
import process from 'process';

const isProd = process.env.NODE_ENV === 'production';

export default {
  mode: isProd ? 'production' : 'development',
  context: process.cwd(),
  entry: {
    // Service worker entry point:
    sw: './src/sw.js',
    // Application entry point:
    app: './src/index.js'
  },
  output: {
    filename: ({runtime}) => {
      // Check if the current filename is for the service worker:
      if (runtime === 'sw') {
        // Output a service worker in the root of the dist directory
        // Also, ensure the output file name doesn't have a hash in it
        return '[name].js';
      }

      // Otherwise, output files as normal
      return 'js/[name].[contenthash:8].js';
    },
    path: './dist',
    publicPath: '/',
    clean: true
  }
};

groupe

La situation de cumul est semblable à celle de webpack, si ce n'est que plusieurs points d'entrée sont spécifiés en tant qu'objets de configuration distincts exportés dans un tableau:

// rollup.config.js
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';

// Plugins common to both entry points
const plugins = [
  nodeResolve(),
];

export default [
  // Application entry point
  {
    input: './src/index.js',
    output: {
      dir: './dist/js',
      format: 'esm'
    },
    plugins
  },
  // Service worker entry point
  {
    input: './src/sw.js',
    output: {
      file: './dist/sw.js',
      format: 'iife'
    },
    plugins: [
      ...plugins,
      // This @rollup/plugin-replace instance replaces process.env.NODE_ENV
      // statements in the Workbox libraries to match your current environment.
      // This changes whether logging is enabled ('development') or disabled ('production').
      replace({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
      })
    ]
  }
];

Esbuild

esbuild propose une interface de ligne de commande simple:

npx esbuild ./src/sw.js --bundle --minify --outfile=./dist/sw.js

esbuild se charge de remplacer process.env.NODE_ENV par "development" par défaut, ou "production" si la minimisation est activée.

Sans bundler en utilisant workbox-sw

Votre projet n'utilise peut-être même pas de bundler. workbox-sw peut charger pour vous l'environnement d'exécution Workbox à partir d'un CDN de votre service worker sans étape de compilation si vous l'importez avec importScripts:

// sw.js

// Imports Workbox from the CDN. Note that "6.2.0" of the URL
// is the version of the Workbox runtime.
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-sw.js');

const navigationRoute = new workbox.routing.NavigationRoute(new workbox.strategies.NetworkFirst({
  cacheName: 'navigations'
}));

const imageAssetRoute = new workbox.routing.Route(({request}) => {
  return request.destination === 'image';
}, new workbox.strategies.CacheFirst({
  cacheName: 'image-assets'
}));

workbox.routing.registerRoute(navigationRoute);
workbox.routing.registerRoute(staticAssetRoute);

Si le chargement de l'environnement d'exécution de la boîte de travail à partir d'un CDN ne semble pas idéal, vous pouvez utiliser workbox-sw avec des URL locales.

Conclusion

Maintenant que vous savez utiliser Workbox sans mise en cache préalable, vous n'êtes plus lié à un bundler ou à un outil de compilation particulier. Vous avez ainsi la possibilité de créer manuellement un service worker en utilisant uniquement les bits du code de mise en cache de l'environnement d'exécution de Workbox qui vous intéresse.