Workbox ohne Precaching verwenden

Bisher ging es in dieser Dokumentation hauptsächlich um das Precaching und die Build-Tools generateSW und injectManifest. Es gibt viele gute Gründe, die Logik für das Vorab-Caching in Ihren Service Worker aufzunehmen. Sie müssen das Vorab-Caching jedoch nicht verwenden, um Workbox zu verwenden.

Möglicherweise ist für Ihr Projekt nur das Laufzeit-Caching erforderlich oder Sie möchten eine sauberere Methode zur Integration von Service Worker APIs, z. B. Web Push. In diesen Fällen sollten Sie die Build-Tools von Workbox nicht verwenden. Genau darauf geht dieser Artikel ein.

Bei Verwendung eines Bundler

Bundler spielen in der Webentwicklung eine wichtige Rolle. Daher ist es sehr wahrscheinlich, dass in Ihrem Projekt ein Bundler verwendet wird. In diesem Fall müssen Sie kein Bundler-Plug-in wie workbox-webpack-plugin verwenden, wenn Sie nichts im Voraus zwischenspeichern. Sie behandeln Ihren Service Worker als separaten Einstiegspunkt in Ihrer Anwendung.

Im Stammverzeichnis des Quellverzeichnisses Ihres Projekts erstellen Sie einen Service Worker und verwenden alle Workbox-Module, die Ihre Anwendung benötigt. Hier ist ein Beispiel ohne Pre-Caching, bei dem stattdessen Caching-Strategien für Navigations- und Bild-Asset-Anfragen in separaten Cache-Instanzen eingerichtet werden:

// 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);

Nun müssen Sie diesen Service Worker als Einstiegspunkt in Ihrem bevorzugten Bundler angeben. Im Folgenden finden Sie einige Beispiele dafür, wie Sie das in einigen gängigen Bundlern tun können.

Webpack

webpack akzeptiert Einstiegspunkte in der entry-Konfiguration. Bei diesem Ansatz sind einige Dinge zu beachten:

  1. Damit Ihr Service Worker möglichst breit gefächert ist, sollten Sie ihn im Stammverzeichnis Ihres Ausgabeverzeichnisses ausgeben.
  2. Sie möchten nicht, dass der Service Worker versioniert wird, da durch Updates neue Hashes generiert werden, was dazu führen kann, dass mehrere Service Worker auf Ihrer Website bereitgestellt werden.

Zur Erfüllung der oben genannten Bedingungen kann eine Funktion an output.filename übergeben werden, die prüft, ob der aktuell verarbeitete Einstiegspunkt der Service Worker-Einstiegspunkt ist. Andernfalls werden versionierte Dateien an ihre normalen Ziele geschrieben.

// 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
  }
};

Rollup

Rollup funktioniert ähnlich wie Webpack, mit der Ausnahme, dass mehrere Einstiegspunkte als separate Konfigurationsobjekte angegeben werden, die in einem Array exportiert werden:

// 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 bietet eine einfache Befehlszeilenschnittstelle:

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

Esbuild ersetzt „process.env.NODE_ENV“ standardmäßig durch „Entwicklung“ oder „Produktion“, wenn die Reduzierung aktiviert ist.

Ohne einen Bundler, der workbox-sw verwendet

Möglicherweise wird in Ihrem Projekt gar kein Bündelungstool verwendet. workbox-sw kann die Workbox-Laufzeit für Sie aus einem CDN in Ihrem Service Worker und ohne Buildschritt laden, wenn Sie sie mit importScripts importieren:

// 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);

Wenn Sie die Workbox-Laufzeit nicht über ein CDN laden möchten, können Sie workbox-sw mit lokalen URLs verwenden.

Fazit

Da Sie jetzt wissen, wie Sie Workbox ohne Pre-Caching verwenden, sind Sie nicht mehr an ein bestimmtes Bündelungs- oder Build-Tool gebunden. So können Sie einen Service Worker mit nur den für Sie relevanten Teilen des Workbox-Laufzeit-Caching-Codes erstellen.