שימוש בתיבת העבודה ללא הגדרה מראש במטמון

עד כה, התיעוד הזה היה גורם משמעותי בהגדרה מראש של המטמון, ובדרך כלל נעשה בו שימוש בכלי ה-build של generateSW ו-injectManifest. יש הרבה סיבות טובות לכלול לוגיקה של טרום-מטמון ב-Service Worker, אבל אתם לא חייבים להשתמש בהרשאה מראש כדי להשתמש ב-Workbox.

אולי הפרויקט שלכם צריך רק שמירה במטמון של זמן ריצה, או אולי אתם רוצים דרך נקייה יותר לשלב ממשקי API של Service Worker, כמו web Push. אלה המקרים שבהם לא רוצים להשתמש בכלי ה-build של Workbox, וזה מה שבמאמר הזה.

בשימוש ב-bundler

חבילות ערוצים בולטות בנוף של פיתוח אתרים, וסביר להניח שבפרויקט שלכם נעשה שימוש. במקרה כזה, חשוב לדעת שאין צורך להשתמש בפלאגין Bundler (כמו workbox-webpack-plugin) כל עוד לא מתבצעת טעינה מראש של קובץ כלשהו. אתם תתייחסו ל-Service Worker כנקודת כניסה נפרדת בבקשה שלכם.

בספריית המקור של הפרויקט יוצרים קובץ שירות (service worker) ומשתמשים בכל המודולים של Workbox שנדרשים לאפליקציה. לפניכם דוגמה ללא הגדרה מראש במטמון, שמגדירה אסטרטגיות שמירה במטמון עבור בקשות של ניווט ובקשות לנכסי תמונות במופעים נפרדים של Cache:

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

מכאן, יש לציין את קובץ השירות (service worker) כנקודת כניסה ב-bundler שבחרת. בהמשך מפורטות כמה דוגמאות לאופן שבו אפשר לעשות זאת בעזרת כמה מקבצים פופולריים.

חבילת אינטרנט

אפשר להשתמש בנקודות כניסה ל-webpack בהגדרות האישיות של entry. יש כמה דברים שכדאי להיות מודעים להם כשבוחרים בגישה הזו:

  1. כדי לוודא שלקובץ השירות (service worker) יש היקף רחב ככל האפשר, עליך לשלוח אותו לשורש של ספריית הפלט.
  2. אתם לא רוצים שתתבצע גרסאות של ה-Service Worker כי עדכונים שלו ייצרו גיבובים חדשים שעלולים לגרום לפריסה של מספר קובצי שירות (service worker) באתר שלך.

כדי לעמוד בתנאים שצוינו, אפשר להעביר פונקציה אל output.filename שבודקת אם נקודת הכניסה הנוכחית בעיבוד היא נקודת הכניסה של קובץ השירות (service worker). אחרת, קבצים עם גרסאות נכתבים ליעדים הרגילים שלהם.

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

אוסף ערוצים

נכס-על הוא מצב דומה ל-Webpack, אלא שנקודות כניסה מרובות מצוינות כאובייקטים נפרדים של הגדרות אישיות שמיוצאים במערך:

// 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 מספק ממשק שורת פקודה פשוט:

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

esbuild יטפל בהחלפת Progress.env.NODE_ENV ב-'development' כברירת מחדל, או ב-'production' אם ההקטנה מופעלת.

ללא Bundler באמצעות workbox-sw

ייתכן שהפרויקט שלכם לא ישתמש אפילו במארז. אם תייבאו אותו באמצעות importScripts, workbox-sw יכול לטעון את זמן הריצה של Workbox מ-CDN בקובץ השירות (service worker) וללא שלב build:

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

אם נראה לכם שאין אפשרות לטעון את זמן הריצה של Workbox מ-CDN, אתם יכולים להשתמש ב-workbox-sw עם כתובות URL מקומיות.

סיכום

עכשיו, אחרי שלמדתם איך להשתמש ב-Workbox בלי להגדיר מראש במטמון, כבר לא תהיו קשורים ל-bundler או לכלי build מסוימים. כך תהיה לך גמישות ליצור קובץ שירות (service worker) רק באמצעות החלקים שמעניינים אותך בקוד השמירה במטמון בזמן הריצה של Workbox.