Utilizzo di Workbox senza memorizzazione nella cache

Finora, questa documentazione ha dato ampio spazio al precaching, spesso toccando gli strumenti di compilazione generateSW e injectManifest. Sebbene esistano molti buoni motivi per includere la logica di precaricamento nel tuo service worker, non è necessario utilizzare il precaricamento per utilizzare Workbox.

Forse il tuo progetto ha bisogno solo della memorizzazione nella cache di runtime o forse vuoi un modo più semplice per integrare le API service worker, come le notifiche push web. Questi sono casi in cui non vuoi utilizzare gli strumenti di compilazione di Workbox e questo è l'argomento trattato in questo articolo.

Quando utilizzi un aggregatore

I bundler sono molto importanti nel panorama dello sviluppo web e c'è una buona probabilità che il tuo progetto ne utilizzi uno. In questo caso, è importante sapere che non devi utilizzare un plug-in per il bundling (come workbox-webpack-plugin) se non esegui il precaching di nulla. Tratterai il tuo service worker come un punto di ingresso separato nell'applicazione.

Nella directory principale della directory di origine del progetto, creerai un service worker e utilizzerai qualsiasi modulo Workbox richiesto dall'applicazione. Di seguito è riportato un esempio senza precaching che configura le strategie di memorizzazione nella cache per le richieste di asset di navigazione e immagine in istanze Cache separate:

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

A questo punto, devi solo specificare questo service worker come punto di contatto nel bundler che preferisci. Di seguito sono riportati alcuni esempi di come eseguire questa operazione in alcuni bundler di uso comune.

webpack

webpack accetta i punti di ingresso nella configurazione di entry. Quando utilizzi questo approccio, tieni presente alcune cose:

  1. Per assicurarti che il tuo worker di servizio abbia l'ambito più ampio possibile, devi impostarlo in modo che venga visualizzato nella directory principale della directory di output.
  2. Non è consigliabile che il service worker esegua il controllo delle versioni, poiché gli aggiornamenti genereranno nuovi hash che potrebbero comportare il deployment di più service worker sul sito web.

Per soddisfare le condizioni precedenti, è possibile passare una funzione a output.filename che esamina se il punto di ingresso corrente in fase di elaborazione è il punto di ingresso del servizio worker. In caso contrario, i file con controllo delle versioni vengono scritti nelle normali destinazioni.

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

aggregazione

Rollup è una situazione simile a webpack, tranne per il fatto che più punti di contatto vengono specificati come oggetti di configurazione separati esportati in un array:

// 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 offre un'interfaccia a riga di comando semplice:

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

esbuild provvederà a sostituire process.env.NODE_ENV con "development" per impostazione predefinita o con "production" se la minimizzazione è abilitata.

Senza un aggregatore che utilizza workbox-sw

Il tuo progetto potrebbe non utilizzare nemmeno un bundler. workbox-sw può caricare il runtime di Workbox da una CDN all'interno del tuo worker di servizio e senza un passaggio di compilazione se lo importi con 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);

Se il potenziale di caricare il runtime di Workbox da una CDN non sembra ottimale, puoi utilizzare workbox-sw con URL locali.

Conclusione

Ora che sai come utilizzare Workbox senza pre-memorizzare nella cache, non devi più avere un bundler o uno strumento di creazione specifico. In questo modo, hai la flessibilità di creare manualmente un service worker utilizzando solo i bit del codice di memorizzazione nella cache di Workbox che ti interessano.