Skip to main content
jg-packages

Search

    Service workers

    jg-sw

    A generated caching worker with a Vite plugin and CLI, plus registration, updates that reload once, and app installation.

    v1.4.0BrowserNode.jsESMMIT

    npm install jg-sw

    Usage

    Register the worker

    ts
    import { registerServiceWorker } from 'jg-sw';
    
    const { registration, registrationError } = await registerServiceWorker(); // registers /sw.js

    It never rejects: a failure lands in registrationError, an Exception whose code is one of ERRORS. Later calls return the first call’s promise, and nothing runs until the first call, so it’s safe to import during server-side rendering.

    Offer updates and installation

    The snapshot tells you when a new version waits and whether the app can be installed. It keeps its identity until something changes, so React can read it directly:

    tsx
    import { useSyncExternalStore } from 'react';
    import { getServiceWorkerSnapshot, installApp, subscribeToServiceWorker, updateApp } from 'jg-sw';
    
    export const AppBanner = () => {
      const { hasWaitingWorker, preloadErrorDetected, installation } = useSyncExternalStore(
        subscribeToServiceWorker,
        getServiceWorkerSnapshot,
        getServiceWorkerSnapshot,
      );
      return (
        <>
          {(hasWaitingWorker || preloadErrorDetected) && (
            <button onClick={() => void updateApp()}>Update</button>
          )}
          {installation.canInstall && <button onClick={() => void installApp()}>Install</button>}
        </>
      );
    };

    Without React, subscribeToServiceWorker(listener) calls the listener on every change and returns a function that stops it.

    updateApp() reloads the page once, never in a loop:

    • When a new version waits, it asks it to activate and reloads once it controls the page.
    • Otherwise it checks for one, waits up to UPDATE_INSTALL_TIMEOUT_SECONDS (30) for it to install, then activates it the same way.
    • When nothing new is found, the installation fails, or the time runs out, it reloads the page as it is.

    preloadErrorDetected turns true when a chunk of a Vite build fails to load while the browser is online and the page has the build’s entry module: the chunk most likely went away with a newer deployment. jg-sw then prevents the vite:preloadError event’s default, so Vite doesn’t throw, and the app offers updateApp(), which loads the new version. A failure while offline, or on a page without an entry module, is left to Vite, so the app’s own error handling shows it. Call registerServiceWorker() as the app starts, so it hears the first failure.

    installApp() shows the browser’s install prompt and resolves to 'accepted' or 'dismissed'. Only Chromium-based browsers offer it, so check canInstallApp() or installation.canInstall first.

    On an iPhone or an iPad, no browser offers an install prompt, and web push works only once the app is installed to the Home Screen. When installing unlocks something your app needs, such as notifications, show your own Add to Home Screen instructions, and only where they apply: isIosBrowserTab() is true in an iOS browser tab, including an iPad that asks for desktop sites, and false in the installed app and everywhere else.

    ts
    import { isIosBrowserTab } from 'jg-sw';
    
    homeScreenHint.hidden = !isIosBrowserTab(); // Share, then Add to Home Screen

    Describe the worker

    Create jg-sw.config.json next to your app’s package.json:

    json
    {
      "outDir": "dist",
      "template": "base",
      "cacheNamePrefix": "my-app",
      "includeToPrecache": ["/assets"],
      "excludeFilesFromPrecache": ["some-ignorable-file.woff2"],
      "excludeMIMETypesFromCache": ["application/json", "text/plain", "text/html"]
    }
    Field What it does
    outDir The directory the app’s build is written to. The worker is written there as sw.js.
    template base caches the app. firebase-fcm also shows Firebase Cloud Messaging notifications.
    cacheNamePrefix The namespace of the worker’s caches, in lowercase words separated by hyphens, such as my-app. Each build caches under <cacheNamePrefix>--<10 characters>.
    includeToPrecache The files and directories, relative to outDir, cached when the worker installs. Directories are read recursively, and / stands for the app’s root page.
    excludeFilesFromPrecache File names left out of precaching, wherever they are.
    excludeMIMETypesFromCache MIME types whose responses are never cached.
    navigationFallback Optional. A precached page, such as /index.html, that answers a navigation the worker can’t serve offline, so a single-page app’s routes still open. The build fails with NAVIGATION_FALLBACK_NOT_PRECACHED when it isn’t precached.

    This config precaches the hashed files under dist/assets, but not / or index.html. Nothing is precached unless it’s listed: add / and /index.html to precache the app’s shell.

    Generate it with Vite

    ts
    // vite.config.ts
    import { defineConfig } from 'vite';
    import { serviceWorkerPlugin } from 'jg-sw/build';
    
    export default defineConfig({
      plugins: [serviceWorkerPlugin({ config: 'jg-sw.config.json' })],
    });

    vite build writes dist/sw.js after the app’s files. vite serves a worker without caching at /sw.js, so you can test registration and updates while every request still reaches the dev server.

    Generate it with the CLI

    Run jg-sw after your build:

    json
    {
      "scripts": {
        "build": "vite build && jg-sw"
      }
    }
    text
    Usage: jg-sw [options]
    
    Options:
      --config <path>        The config file. Defaults to jg-sw.config.json.
      --environment <name>   development, staging, or production.
      --no-caching           Generates a worker without precaching, cache cleanup, or a fetch handler.
      --help                 Prints this message.

    It prints the path it wrote and exits 0, or prints the error and exits 1.

    Generate it from code

    ts
    import { readServiceWorkerConfig, writeServiceWorker } from 'jg-sw/build';
    
    const config = await readServiceWorkerConfig('jg-sw.config.json');
    await writeServiceWorker(config, { environment: 'production' }); // '/app/dist/sw.js'

    buildServiceWorker returns the worker’s source without writing it.

    What the worker does

    • install fills only the new version’s cache, and doesn’t skip waiting, so the previous worker keeps serving its clients.
    • The page activates a waiting worker by posting { type: 'JG_SW_SKIP_WAITING' } to it.
    • activate deletes the older caches in its own namespace, keeps every other cache, then claims its clients.
    • It answers same-origin GET requests from the current version’s cache, then from the network, and caches successful responses unless they’re opaque, partial, marked Vary: *, marked Cache-Control: no-store or private, or of an excluded MIME type. A failed cache write never replaces a valid response.
    • When a navigation is in neither its cache nor the network’s reach, such as offline, it answers with the navigationFallback page when one is set, and otherwise with a 408 network error. A 4xx or 5xx from the server is passed through as it is.

    Firebase Cloud Messaging

    The firebase-fcm template adds two fields:

    json
    {
      "template": "firebase-fcm",
      "firebaseConfigProcessEnvKey": "VITE_FIREBASE_CONFIG",
      "firebaseSdkVersion": "12.4.0"
    }

    The environment variable holds the Firebase web app’s options as JSON:

    bash
    VITE_FIREBASE_CONFIG='{"options":{"apiKey":"example-api-key","authDomain":"example.firebaseapp.com","projectId":"example-project","storageBucket":"example.firebasestorage.app","messagingSenderId":"123456789012","appId":"1:123456789012:web:example"}}'

    Generate the worker with an environment, such as jg-sw --environment production. It loads .env, .env.staging, or .env.production when the file exists, and variables already set keep their values.

    The worker loads Firebase’s compat SDK from gstatic. When no app window is visible, it shows a notification for each data-only message, using its title, body, icon, badge, and url fields, and Firebase shows the messages that carry a notification. Clicking a notification focuses or opens its URL, limited to the app’s origin. To decide yourself, append code to the generated worker that assigns self.jgSwFcmBackgroundMessageHandler = async (payload) => { … }. The worker waits for it, and shows nothing else.

    Generated from TSDoc

    API reference

    Every export of [email protected], 27 in all, with its signature, its errors, and an example.

    jg-sw

    Functionsjg-sw

    canInstallApp
    function

    Checks whether installApp can show the installation prompt now: the browser offered one, and the page doesn't already run as the installed app. Only Chromium-based browsers offer it.

    Signature
    canInstallApp(): boolean

    Returns

    boolean

    Whether the app can be installed.

    Example
    import { canInstallApp } from 'jg-sw';
    
    installButton.hidden = !canInstallApp();
    getServiceWorkerSnapshot
    function

    Reads the service worker's state: its registration, its newest worker, whether an update waits, and whether the app can be installed. The same object comes back until something changes, so it can be passed to React's useSyncExternalStore, during server rendering too.

    Signature
    getServiceWorkerSnapshot(): IServiceWorkerSnapshot

    Returns

    IServiceWorkerSnapshot

    The snapshot.

    Example
    import { getServiceWorkerSnapshot, subscribeToServiceWorker } from 'jg-sw';
    
    const { hasWaitingWorker, installation } = useSyncExternalStore(
      subscribeToServiceWorker,
      getServiceWorkerSnapshot,
      getServiceWorkerSnapshot,
    );
    installApp
    function

    Shows the browser's installation prompt and resolves to the user's answer, also kept in the snapshot as installation.promptOutcome. The browser offers each prompt once, so canInstallApp is false afterwards until it offers another.

    Signature
    installApp(): Promise<IInstallationPromptOutcome>

    Returns

    Promise<IInstallationPromptOutcome>

    A promise that resolves to 'accepted' or 'dismissed'.

    Throws

    • NO_APP_INSTALLERThe app can't be installed because the browser didn't offer the prompt.
    • UNKNOWN_INSTALLATION_PROMPT_ERRORThe installation prompt failed.
    Example
    import { installApp } from 'jg-sw';
    
    installButton.addEventListener('click', async () => {
      const outcome = await installApp(); // 'accepted' or 'dismissed'
    });
    isIosBrowserTab
    function

    Checks whether the page runs in a browser tab on an iPhone, an iPad, or an iPod touch, rather than as an app installed to the Home Screen. There, web push and some storage only work once the app is installed, and no browser offers an install prompt, so this decides when to show your own Add to Home Screen instructions. An iPad that asks for desktop sites reports a Mac, so a Mac with a touchscreen counts as one.

    Signature
    isIosBrowserTab(): boolean

    Returns

    boolean

    Whether it's an iOS browser tab; false outside a browser.

    Example
    import { isIosBrowserTab } from 'jg-sw';
    
    homeScreenHint.hidden = !isIosBrowserTab();
    registerServiceWorker
    function

    Registers the service worker and starts following its updates, whether the app can be installed, and whether a chunk of a replaced build failed to load, which sets the snapshot's preloadErrorDetected. Call it as the app starts, so it hears the first failure. Later calls return the first call's promise. It never rejects: a failure lands in the snapshot's registrationError, an Exception with SW_NO_BROWSER_SUPPORT, EMPTY_SW_REGISTRATION, or SW_REGISTRATION_FAILED as its code, and the browser's error as its cause.

    Signature
    registerServiceWorker(
      options?: IRegisterServiceWorkerOptions,
    ): Promise<IServiceWorkerSnapshot>

    Parameters

    options?IRegisterServiceWorkerOptions

    The worker's path and registration options, and whether to log.

    Defaults to {}.

    Returns

    Promise<IServiceWorkerSnapshot>

    A promise that resolves to the snapshot once the registration settles.

    Example
    import { hasErrorCode } from 'jg-exception';
    import { ERRORS, registerServiceWorker } from 'jg-sw';
    
    const { registration, registrationError } = await registerServiceWorker();
    if (hasErrorCode(registrationError, ERRORS.SW_NO_BROWSER_SUPPORT)) {
      // the browser has no service workers
    }
    subscribeToServiceWorker
    function

    Calls a listener whenever the snapshot changes, such as when an update finishes installing or the app becomes installable.

    Signature
    subscribeToServiceWorker(listener: () => void): () => void

    Parameters

    listener() => void

    The function to call, without arguments; read the new state with getServiceWorkerSnapshot.

    Returns

    () => void

    A function that stops the calls.

    Example
    import { getServiceWorkerSnapshot, subscribeToServiceWorker } from 'jg-sw';
    
    const unsubscribe = subscribeToServiceWorker(() => {
      if (getServiceWorkerSnapshot().hasWaitingWorker) {
        showUpdateBanner();
      }
    });
    updateApp
    function

    Updates the app to its newest version and reloads the page once, never in a loop. When a new version waits, it activates it and reloads once the new worker controls the page. Otherwise, it checks for one, waits up to UPDATE_INSTALL_TIMEOUT_SECONDS for it to install, then activates it the same way. When nothing new is found, the installation fails, or the time runs out, it reloads the page as it is.

    Signature
    updateApp(): Promise<void>

    Returns

    Promise<void>

    A promise that resolves once the new worker was asked to activate, or the page started reloading.

    Example
    import { getServiceWorkerSnapshot, updateApp } from 'jg-sw';
    
    if (getServiceWorkerSnapshot().hasWaitingWorker) {
      updateButton.addEventListener('click', () => updateApp());
    }

    Constantsjg-sw

    DEFAULT_SERVICE_WORKER_PATH
    const

    the path the runtime registers the worker from, and the Vite plugin serves it at in development

    Declaration
    const DEFAULT_SERVICE_WORKER_PATH: "/sw.js"
    ERRORS
    const

    the codes for every error thrown or reported by the runtime

    Declaration
    const ERRORS: { SW_NO_BROWSER_SUPPORT: "SW_NO_BROWSER_SUPPORT"; EMPTY_SW_REGISTRATION: "EMPTY_SW_REGISTRATION"; SW_REGISTRATION_FAILED: "SW_REGISTRATION_FAILED"; NO_APP_INSTALLER: "NO_APP_INSTALLER"; UNKNOWN_INSTALLATION_PROMPT_ERROR: "UNKNOWN_INSTALLATION_PROMPT_ERROR" }
    REGISTRATION_DURATION_SECONDS
    const

    the seconds a registration usually takes, for apps that wait before reading the snapshot

    Declaration
    const REGISTRATION_DURATION_SECONDS: 5
    SKIP_WAITING_MESSAGE_TYPE
    const

    the type of the message the runtime posts to make a waiting worker activate

    Declaration
    const SKIP_WAITING_MESSAGE_TYPE: "JG_SW_SKIP_WAITING"
    UPDATE_INSTALL_TIMEOUT_SECONDS
    const

    the seconds updateApp waits for a new worker to finish installing before it reloads anyway

    Declaration
    const UPDATE_INSTALL_TIMEOUT_SECONDS: 30

    Interfacesjg-sw

    IBeforeInstallPromptEvent
    interface

    the event Chromium-based browsers fire when the app can be installed, which lets the app show the installation prompt when it chooses

    Declaration
    interface IBeforeInstallPromptEvent extends Event {
        readonly platforms: string[];
        readonly userChoice: Promise<IUserChoice>;
        prompt(): Promise<void>;
    }

    Members

    • platformsproperty
      string[]

      the platforms the event was dispatched for, such as 'web' or 'play'

    • userChoiceproperty
      Promise<IUserChoice>

      resolves to the user's answer once the prompt closes

    • promptmethod
      prompt(): Promise<void>

      shows the installation prompt

    Typesjg-sw

    IAppInstallationState
    type

    whether the app can be installed, and what happened when it was offered

    Declaration
    type IAppInstallationState = {
        canInstall: boolean;
        isAppInstalled: boolean | undefined;
        isRunningInstalledApp: boolean;
        promptOutcome: IInstallationPromptOutcome | undefined;
    };

    Members

    • canInstallproperty
      boolean

      whether installApp can show the installation prompt now

    • isAppInstalledproperty
      boolean | undefined

      true once the browser reports the app was installed, undefined until then

    • isRunningInstalledAppproperty
      boolean

      whether the page runs as the installed app, in a standalone window

    • promptOutcomeproperty
      IInstallationPromptOutcome | undefined

      the user's answer to the last prompt installApp showed, undefined until one is answered

    IInstallationPromptOutcome
    type

    the action the user took on the installation prompt

    Declaration
    type IInstallationPromptOutcome = 'accepted' | 'dismissed';
    IRegisterServiceWorkerOptions
    type

    the options registerServiceWorker accepts

    Declaration
    type IRegisterServiceWorkerOptions = {
        path?: string;
        options?: RegistrationOptions;
        debugMode?: boolean;
    };

    Members

    • pathproperty
      string

      the worker's script. Defaults to DEFAULT_SERVICE_WORKER_PATH, '/sw.js'

    • optionsproperty
      RegistrationOptions

      the options passed to navigator.serviceWorker.register. Defaults to { scope: '/' }

    • debugModeproperty
      boolean

      logs the registration, update, and installation events to the console

    IServiceWorkerSnapshot
    type

    the service worker's state. The object keeps its identity until something changes, so useSyncExternalStore(subscribeToServiceWorker, getServiceWorkerSnapshot) re-renders only on changes

    Declaration
    type IServiceWorkerSnapshot = {
        registration: ServiceWorkerRegistration | undefined;
        worker: ServiceWorker | undefined;
        registrationError: Exception | undefined;
        hasWaitingWorker: boolean;
        preloadErrorDetected: boolean;
        installation: IAppInstallationState;
    };

    Members

    • registrationproperty
      ServiceWorkerRegistration | undefined

      the registration, once registerServiceWorker succeeds

    • workerproperty
      ServiceWorker | undefined

      the newest worker: the installing one, else the waiting one, else the active one

    • registrationErrorproperty
      Exception | undefined

      why the registration failed, with one of the ERRORS codes

    • hasWaitingWorkerproperty
      boolean

      whether a new version is installed and waits to activate, which updateApp does

    • preloadErrorDetectedproperty
      boolean

      whether a chunk of the page's build failed to load while online, most likely because a newer deployment replaced it; updateApp loads the new version

    • installationproperty
      IAppInstallationState

      whether the app can be installed, and what happened when it was offered

    IUserChoice
    type

    the user's answer to the installation prompt

    Declaration
    type IUserChoice = {
        outcome: IInstallationPromptOutcome;
        platform: string;
    };

    Members

    • outcomeproperty
      IInstallationPromptOutcome
    • platformproperty
      string

    jg-sw/build

    Functionsjg-sw/build

    buildServiceWorker
    function

    Generates the service worker's source from a config, without writing it. Every generated worker gets a new cache name, <cacheNamePrefix>--<10 random characters>, so a new deployment replaces the previous one's cache when it activates.

    Signature
    buildServiceWorker(
      config: { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string },
      options?: IBuildServiceWorkerOptions,
    ): Promise<string>

    Parameters

    config{ outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string }

    The service worker config, as read by readServiceWorkerConfig or written inline.

    options?IBuildServiceWorkerOptions

    The environment the firebase-fcm template reads its Firebase config from, whether the worker caches (false for development), and the directory paths are resolved from.

    Defaults to {}.

    Returns

    Promise<string>

    A promise that resolves to the worker's source.

    Throws

    • FAILED_TO_READ_BASE_CONFIGThe service worker config is invalid.
    • INVALID_TEMPLATE_NAMEThe template must be 'base' or 'firebase-fcm'.
    • INVALID_FIREBASE_SDK_VERSIONThe Firebase SDK version must be a version such as 12.4.0.
    • INVALID_ENVIRONMENTThe environment isn't supported, or the firebase-fcm template needs one.
    • NOT_A_PATH_ELEMENTAn asset to precache is outside outDir, or isn't a file or a directory.
    • NAVIGATION_FALLBACK_NOT_PRECACHEDThe navigation fallback isn't one of the precached paths.
    • FAILED_TO_BUILD_CONFIGUnable to load the environment file.
    • INVALID_FIREBASE_CONFIGThe environment variable that holds the Firebase config is missing or
    • Errorempty.
    • FAILED_TO_READ_FIREBASE_CONFIGUnable to read the Firebase config from the environment
    • Errorvariable.
    Example
    import { buildServiceWorker } from 'jg-sw/build';
    
    const source = await buildServiceWorker(
      {
        outDir: 'dist',
        cacheNamePrefix: 'my-app',
        template: 'base',
        includeToPrecache: ['/', '/assets'],
        excludeFilesFromPrecache: [],
        excludeMIMETypesFromCache: ['application/json'],
      },
      { caching: true },
    );
    readServiceWorkerConfig
    function

    Reads and validates a service worker config file, such as jg-sw.config.json.

    Signature
    readServiceWorkerConfig(
      path: string,
    ): Promise<{ outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string }>

    Parameters

    pathstring

    The config file's path.

    Returns

    Promise<{ outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string }>

    A promise that resolves to the config.

    Throws

    • FAILED_TO_READ_BASE_CONFIGUnable to read the service worker config, or it is invalid.
    • INVALID_TEMPLATE_NAMEThe template must be 'base' or 'firebase-fcm'.
    • INVALID_FIREBASE_SDK_VERSIONThe Firebase SDK version must be a version such as 12.4.0.
    Example
    import { readServiceWorkerConfig } from 'jg-sw/build';
    
    const config = await readServiceWorkerConfig('jg-sw.config.json');
    config.template; // 'base'
    serviceWorkerPlugin
    function

    Creates a Vite plugin that generates the service worker. After a production build, it writes sw.js into the config's outDir, once the client bundle is written. During development, the dev server answers /sw.js with a worker generated with caching: false, so every request reaches the dev server and updates show up without stale caches. Paths are resolved from Vite's root unless cwd is set. When generating fails, the build fails with writeServiceWorker's error, and the dev server answers the worker's request with it.

    Signature
    serviceWorkerPlugin(
      options: { config: string | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string } } & IBuildServiceWorkerOptions,
    ): Plugin

    Parameters

    options{ config: string | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string } } & IBuildServiceWorkerOptions

    The config, as a file path or an object, plus the build options. The dev server uses the environment option, or development when it isn't set.

    Returns

    Plugin

    The Vite plugin.

    Example
    // vite.config.ts
    import { defineConfig } from 'vite';
    import { serviceWorkerPlugin } from 'jg-sw/build';
    
    export default defineConfig({
      plugins: [serviceWorkerPlugin({ config: 'jg-sw.config.json', environment: 'production' })],
    });
    writeServiceWorker
    function

    Generates the service worker and writes it to sw.js in the config's outDir, after the app's build has written its files there.

    Signature
    writeServiceWorker(
      config: { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string },
      options?: IBuildServiceWorkerOptions,
    ): Promise<string>

    Parameters

    config{ outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "base" } | { outDir: string; cacheNamePrefix: string; includeToPrecache: string[]; excludeFilesFromPrecache: string[]; excludeMIMETypesFromCache: string[]; navigationFallback?: string; template: "firebase-fcm"; firebaseConfigProcessEnvKey: string; firebaseSdkVersion: string }

    The service worker config, as read by readServiceWorkerConfig or written inline.

    options?IBuildServiceWorkerOptions

    The environment the firebase-fcm template reads its Firebase config from, whether the worker caches (false for development), and the directory paths are resolved from.

    Defaults to {}.

    Returns

    Promise<string>

    A promise that resolves to the written file's path.

    Throws

    • FAILED_TO_READ_BASE_CONFIGThe service worker config is invalid.
    • INVALID_TEMPLATE_NAMEThe template must be 'base' or 'firebase-fcm'.
    • INVALID_FIREBASE_SDK_VERSIONThe Firebase SDK version must be a version such as 12.4.0.
    • INVALID_ENVIRONMENTThe environment isn't supported, or the firebase-fcm template needs one.
    • NOT_A_PATH_ELEMENTAn asset to precache is outside outDir, or isn't a file or a directory.
    • NAVIGATION_FALLBACK_NOT_PRECACHEDThe navigation fallback isn't one of the precached paths.
    • FAILED_TO_BUILD_CONFIGUnable to load the environment file.
    • INVALID_FIREBASE_CONFIGThe environment variable that holds the Firebase config is missing or
    • Errorempty.
    • FAILED_TO_READ_FIREBASE_CONFIGUnable to read the Firebase config from the environment
    • Errorvariable.
    Example
    import { readServiceWorkerConfig, writeServiceWorker } from 'jg-sw/build';
    
    const config = await readServiceWorkerConfig('jg-sw.config.json');
    await writeServiceWorker(config, { environment: 'production' }); // '/app/dist/sw.js'

    Constantsjg-sw/build

    ERRORS
    const

    the codes for every error thrown by the build side

    Declaration
    const ERRORS: { INVALID_TEMPLATE_NAME: "INVALID_TEMPLATE_NAME"; NOT_A_PATH_ELEMENT: "NOT_A_PATH_ELEMENT"; FAILED_TO_READ_BASE_CONFIG: "FAILED_TO_READ_BASE_CONFIG"; INVALID_FIREBASE_CONFIG: "INVALID_FIREBASE_CONFIG"; INVALID_ENVIRONMENT: "INVALID_ENVIRONMENT"; FAILED_TO_BUILD_CONFIG: "FAILED_TO_BUILD_CONFIG"; FAILED_TO_READ_FIREBASE_CONFIG: "FAILED_TO_READ_FIREBASE_CONFIG"; INVALID_FIREBASE_SDK_VERSION: "INVALID_FIREBASE_SDK_VERSION"; NAVIGATION_FALLBACK_NOT_PRECACHED: "NAVIGATION_FALLBACK_NOT_PRECACHED" }
    ServiceWorkerConfigSchema
    const

    The schema of a service worker config: the jg-sw.config.json file the CLI reads, or the object passed to buildServiceWorker. template selects the worker: base caches the app, and firebase-fcm also shows Firebase Cloud Messaging notifications.

    Declaration
    const ServiceWorkerConfigSchema: ZodDiscriminatedUnion<[ZodObject<{ outDir: ZodString; cacheNamePrefix: ZodString; includeToPrecache: ZodArray<ZodString>; excludeFilesFromPrecache: ZodArray<ZodString>; excludeMIMETypesFromCache: ZodArray<ZodString>; navigationFallback: ZodOptional<ZodString>; template: ZodLiteral<"base"> }, $strict>, ZodObject<{ outDir: ZodString; cacheNamePrefix: ZodString; includeToPrecache: ZodArray<ZodString>; excludeFilesFromPrecache: ZodArray<ZodString>; excludeMIMETypesFromCache: ZodArray<ZodString>; navigationFallback: ZodOptional<ZodString>; template: ZodLiteral<"firebase-fcm">; firebaseConfigProcessEnvKey: ZodString; firebaseSdkVersion: ZodString }, $strict>], "template">
    Example
    import { ServiceWorkerConfigSchema } from 'jg-sw/build';
    
    const config = ServiceWorkerConfigSchema.parse({
      outDir: 'dist',
      cacheNamePrefix: 'my-app',
      template: 'base',
      includeToPrecache: ['/', '/index.html', '/assets'],
      excludeFilesFromPrecache: [],
      excludeMIMETypesFromCache: ['application/json'],
    });

    Typesjg-sw/build

    IBuildServiceWorkerOptions
    type

    the options buildServiceWorker and writeServiceWorker accept

    Declaration
    type IBuildServiceWorkerOptions = {
        environment?: 'development' | 'staging' | 'production';
        caching?: boolean;
        cwd?: string;
    };

    Members

    • environmentproperty
      "development" | "staging" | "production"

      the environment whose file the firebase-fcm template reads its Firebase config from: .env, .env.staging, or .env.production. The firebase-fcm template requires it

    • cachingproperty
      boolean

      false leaves out precaching, cache cleanup, and the fetch handler, for development. Defaults to true

    • cwdproperty
      string

      the directory outDir and the environment files are resolved from. Defaults to process.cwd()

    IServiceWorkerConfig
    type

    a service worker config, validated by ServiceWorkerConfigSchema

    Declaration
    type IServiceWorkerConfig = z.infer<typeof ServiceWorkerConfigSchema>;