Utilizzo di Workbox senza memorizzazione nella cache

Finora questa documentazione è stata molto utile per quanto riguarda la pre-memorizzazione nella cache, spesso affrontando gli strumenti di creazione di generateSW e injectManifest. Anche se esistono molti buoni motivi per includere la logica di pre-memorizzazione nella cache nel service worker, non devi necessariamente ricorrere alla pre-memorizzazione nella cache per utilizzare Workbox.

Magari il tuo progetto necessita solo della memorizzazione nella cache di runtime o potresti volere un modo più semplice per integrare le API dei service worker, ad esempio il push web. In questi casi non vorrai utilizzare gli strumenti di creazione di Workbox e si tratta di quanto descritto in questo articolo.

Quando si utilizza un bundler

I bundler sono importanti nel panorama dello sviluppo web ed è molto probabile che il tuo progetto ne utilizzi uno. In questo caso, tieni presente che non è necessario utilizzare un plug-in bundler (come workbox-webpack-plugin) se non stai eseguendo alcuna pre-memorizzazione nella cache. Tratterai il service worker come un punto di ingresso separato nella tua applicazione.

Nella directory principale della directory di origine del progetto, creerai un service worker e utilizzerai qualsiasi modulo di Workbox richiesto dall'applicazione. Ecco un esempio senza pre-memorizzazione nella cache, che imposta invece le strategie di memorizzazione nella cache per la navigazione e le richieste di asset 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);

Da qui, si tratta di specificare questo service worker come punto di ingresso nel tuo bundler preferito. Di seguito sono riportati alcuni esempi di come farlo in alcuni dei bundler più diffusi.

webpack

webpack accetta punti di ingresso nella sua configurazione di entry. Ci sono un paio di aspetti da tenere presenti quando si utilizza questo approccio:

  1. Per assicurarti che il service worker abbia l'ambito più ampio possibile, ti consigliamo di generare l'output nella directory principale della directory di output.
  2. Non vuoi che il service worker abbia il controllo delle versioni, perché gli aggiornamenti genereranno nuovi hash che potrebbero comportare il deployment di più service worker sul tuo sito web.

Per soddisfare le condizioni di cui sopra, è possibile passare una funzione a output.filename che verifica se il punto di ingresso attuale in fase di elaborazione è quello del service worker. In caso contrario, i file sottoposti al controllo delle versioni vengono scritti nelle loro 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
  }
};

raggruppamento

L'elemento aggregazione è una situazione simile a webpack, tranne per il fatto che più punti di ingresso 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 una semplice interfaccia a riga di comando:

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

esbuild si occuperà di sostituire process.env.NODE_ENV con "development" per impostazione predefinita o con "produzione" se la minimizzazione è abilitata.

Senza un bundler che utilizza workbox-sw

Il tuo progetto potrebbe non utilizzare nemmeno un bundler. workbox-sw può caricare automaticamente il runtime Workbox da una CDN all'interno del tuo service worker e senza un passaggio di build 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 la possibilità di caricare il runtime Workbox da una CDN non ti sembra eccessiva, puoi utilizzare workbox-sw con URL locali.

Conclusione

Ora che sai come utilizzare Workbox senza pre-memorizzazione nella cache, non sei più legato a un particolare bundler o strumento di creazione. Questo ti offre la flessibilità di realizzare manualmente un service worker utilizzando solo i frammenti del codice di memorizzazione nella cache di runtime di Workbox che ti interessano.