Menggunakan Workbox tanpa precaching

Sejauh ini, dokumentasi ini sangat penting terkait precache, sering kali menyentuh alat build generateSW dan injectManifest. Meskipun ada banyak alasan bagus untuk memasukkan logika precaching di pekerja layanan, Anda tidak perlu menggunakan precaching untuk menggunakan Workbox.

Mungkin project Anda hanya memerlukan cache runtime, atau mungkin Anda menginginkan cara yang lebih bersih untuk mengintegrasikan API pekerja layanan, seperti web push. Ini adalah kasus ketika Anda tidak ingin menggunakan alat build Workbox, dan itulah yang dibahas dalam artikel ini.

Saat menggunakan bundler

Bundler menonjol dalam lanskap pengembangan web, dan ada kemungkinan project Anda menggunakannya. Jika demikian, penting untuk diketahui bahwa Anda tidak perlu menggunakan plugin pemaket (seperti workbox-webpack-plugin) jika tidak melakukan precaching apa pun. Anda akan memperlakukan pekerja layanan sebagai titik entri terpisah dalam aplikasi.

Di root direktori sumber project, Anda akan membuat pekerja layanan dan menggunakan modul Workbox apa pun yang diperlukan aplikasi. Berikut adalah contoh tanpa precache, yang menyiapkan strategi caching untuk permintaan aset gambar dan navigasi dalam instance Cache terpisah:

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

Dari sini, tinggal menentukan pekerja layanan ini sebagai titik entri dalam pemaket pilihan Anda. Berikut adalah beberapa contoh cara melakukannya di beberapa pemaket populer.

webpack

webpack menerima titik entri dalam konfigurasi entry-nya. Ada beberapa hal yang perlu diperhatikan saat menggunakan pendekatan ini:

  1. Untuk memastikan service worker memiliki cakupan seluas mungkin, Anda ingin pekerja itu menjadi {i>output<i} ke root direktori output.
  2. Anda tidak ingin pekerja layanan memiliki versi, karena updatenya akan menghasilkan hash baru yang dapat menyebabkan beberapa pekerja layanan di-deploy di situs Anda.

Untuk memenuhi kondisi di atas, fungsi dapat diteruskan ke output.filename yang memeriksa apakah titik entri saat ini yang diproses adalah titik entri pekerja layanan. Jika tidak, file berversi ditulis ke tujuan normalnya.

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

penggabungan

Gabungan adalah situasi yang serupa dengan webpack, kecuali beberapa titik entri ditentukan sebagai objek konfigurasi terpisah yang diekspor dalam 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 menawarkan antarmuka command line yang mudah:

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

esbuild akan menangani penggantian process.env.diatasi_ENV dengan 'development' secara default, atau 'production' jika minifikasi diaktifkan.

Tanpa bundler yang menggunakan workbox-sw

Project Anda bahkan mungkin tidak menggunakan bundler. workbox-sw dapat memuat runtime Workbox untuk Anda dari CDN dalam pekerja layanan dan tanpa langkah build jika Anda mengimpornya dengan 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);

Jika prospek pemuatan runtime Workbox dari CDN tidak tampak bagus, Anda dapat menggunakan workbox-sw dengan URL lokal.

Kesimpulan

Setelah mengetahui cara menggunakan Workbox tanpa melakukan precaching, Anda tidak lagi terikat dengan bundler atau alat build tertentu. Hal ini memberi Anda fleksibilitas untuk membuat pekerja layanan secara manual hanya dengan menggunakan bit kode penyimpanan dalam cache runtime Workbox yang Anda minati.