Workbox ohne Precaching verwenden

Bisher ging es in dieser Dokumentation hauptsächlich um das Precaching und ging dabei oft auf die Build-Tools generateSW und injectManifest ein. Es gibt viele gute Gründe, die Precaching-Logik in Ihren Service Worker einzubinden, aber Sie müssen kein Precaching verwenden, um Workbox nutzen zu können.

Vielleicht benötigt Ihr Projekt nur Laufzeit-Caching oder Sie möchten eine sauberere Methode zur Integration von Service Worker APIs wie Web-Push. Dies sind Fälle, in denen Sie die Build-Tools von Workbox nicht verwenden möchten. Darauf wird in diesem Artikel eingegangen.

Bei Verwendung eines Bundler

Bundler sind in der Webentwicklung sehr bekannt und es ist sehr wahrscheinlich, dass sie in Ihrem Projekt verwendet werden. In diesem Fall ist es wichtig zu wissen, dass Sie kein Bundler-Plug-in wie workbox-webpack-plugin verwenden müssen, wenn Sie nichts im Cache speichern. Sie betrachten Ihren Service Worker als separaten Einstiegspunkt in Ihrer Anwendung.

Im Stammverzeichnis des Quellverzeichnisses Ihres Projekts erstellen Sie einen Service Worker und verwenden die Workbox-Module, die für Ihre Anwendung erforderlich sind. In diesem Beispiel ohne Precaching werden Caching-Strategien für Navigations- und Bild-Asset-Anfragen stattdessen in separaten Cache-Instanzen eingerichtet:

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

Jetzt müssen Sie diesen Service Worker als Einstiegspunkt in Ihrem gewünschten Bundler festlegen. Im Folgenden findest du einige Beispiele dafür, wie dies in einigen beliebten Bundler funktioniert.

Webpack

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

  1. Damit Ihr Service Worker den größtmöglichen Umfang hat, sollte er in das Stammverzeichnis Ihres Ausgabeverzeichnisses ausgegeben werden.
  2. Sie möchten nicht, dass der Service Worker versioniert wird, da durch seine Aktualisierung neue Hashes generiert werden. Dies kann dazu führen, dass mehrere Service Worker auf Ihrer Website bereitgestellt werden.

Um die oben genannten Bedingungen zu erfüllen, 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

Ein Rollup ist ähnlich wie bei Webpack, mit dem Unterschied, dass mehrere Einstiegspunkte als separate Konfigurationsobjekte angegeben sind, 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 sorgt dafür, dass process.env.NODE_ENV standardmäßig durch "development" ersetzt wird oder durch "production", wenn die Reduzierung aktiviert ist.

Ohne einen Bundler mit workbox-sw

Ihr Projekt verwendet möglicherweise nicht einmal einen Bundler. workbox-sw kann die Workbox-Laufzeit für Sie aus einem CDN innerhalb Ihres Service Workers und ohne Build-Schritt 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 die Aussicht, die Workbox-Laufzeit aus einem CDN zu laden, nicht gut aussieht, ist es möglich, workbox-sw mit lokalen URLs zu verwenden.

Fazit

Da Sie jetzt wissen, wie Sie Workbox ohne Precaching verwenden, sind Sie nicht mehr an einen bestimmten Bundler oder ein Build-Tool gebunden. Dies gibt Ihnen die Flexibilität, einen Service Worker mit nur den für Sie relevanten Bits des Laufzeit-Caching-Codes von Workbox manuell zu erstellen.