### Install and Activate PrecacheController Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-precaching/static/precache.html Use these event listeners to manage the precaching lifecycle by adding files to the controller and invoking install or activate methods. ```javascript self.registration = { scope: 'injected-scope', }; let lastInstallValues = []; let flipFile = 'example-a.html'; const installBtn = document.querySelector('.js-index-install'); installBtn.addEventListener('click', (event) => { const precacheController = new workbox.precaching.PrecacheController(); lastInstallValues = [ './project/index.html', `./project/${flipFile}`, {url: './project/example.html'}, {url: './project/example-2.html', revision: '123'}, {url: './project/example-timestamp.html', revision: Date.now()}, ]; precacheController.addToCacheList(lastInstallValues); precacheController.install(event); if (flipFile === 'example-a.html') { flipFile = 'example-b.html'; } else { flipFile = 'example-a.html'; } }); const activateBtn = document.querySelector('.js-index-activate'); activateBtn.addEventListener('click', (event) => { const precacheController = new workbox.precaching.PrecacheController(); precacheController.addToCacheList(lastInstallValues); precacheController.activate(event); }); ``` -------------------------------- ### Build and Test Workbox Locally Source: https://github.com/googlechrome/workbox/blob/v7/CONTRIBUTING.md Commands to install dependencies, build the project, and execute the full test suite. ```sh $ npm ci $ npm run gulp build $ npm run gulp test ``` -------------------------------- ### Install and Interact with Service Worker Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-core/index.html This JavaScript code snippet handles the installation of a service worker and sets up event listeners for buttons to trigger logging and cache name display. Ensure the service worker file ('/sw.js') is correctly configured. ```javascript const installSWBtn = document.querySelector('.install-sw'); const showLogsBtn = document.querySelector('.show-logs'); const cacheNamesBtn = document.querySelector('.show-cache-names'); installSWBtn.addEventListener('click', () => { console.log('Installing service worker'); navigator.serviceWorker.register('/sw.js').then((reg) => { showLogsBtn.addEventListener('click', () => { const message = { command: 'printLogs', }; reg.active.postMessage(message); }); cacheNamesBtn.addEventListener('click', () => { const message = { command: 'printCacheNames', }; reg.active.postMessage(message); }); }); }); ``` -------------------------------- ### Launch Browser Test Server Source: https://github.com/googlechrome/workbox/blob/v7/CONTRIBUTING.md Starts the local test server for browser-based code, accessible at http://localhost:3004/. ```sh npm run gulp test_server ``` -------------------------------- ### Start Local Test Server Source: https://github.com/googlechrome/workbox/wiki/Testing Launch a local test server to manually inspect endpoints and behavior in a browser outside of a webdriver controller. ```shell gulp test-server ``` -------------------------------- ### Install Service Worker Button Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-sw/index.html This JavaScript code registers a service worker when a button is clicked. Ensure the button with the class 'install-sw' exists in your HTML. ```javascript const installSWBtn = document.querySelector('.install-sw'); installSWBtn.addEventListener('click', () => { navigator.serviceWorker.register('./sw.js'); }); ``` -------------------------------- ### Define named webpack chunks Source: https://github.com/googlechrome/workbox/wiki/webpack-Plugin-Info Example of a webpack configuration defining multiple entry points, resulting in named chunks. ```js const webpackConfig = { entry: { chunk1: './path/to/my/entry/file1.js', chunk2: './path/to/my/entry/file2.js' }, // etc. } ``` -------------------------------- ### Initialize Google Analytics and Service Worker Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-google-analytics/index.html Standard Google Analytics initialization script combined with service worker registration and event listener setup for tracking clicks. ```javascript (function (i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r; (i[r] = i[r] || function () { (i[r].q = i[r].q || []).push(arguments); }), (i[r].l = 1 * new Date()); (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]); a.async = 1; a.src = g; m.parentNode.insertBefore(a, m); })( window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga', ); ga('create', 'UA-77119321-5', 'auto'); const analyticsCallBtn = document.querySelector('.make-analytics-call'); navigator.serviceWorker.register('./sw.js').then((reg) => { analyticsCallBtn.addEventListener('click', () => { ga('send', 'pageview'); }); }); ``` -------------------------------- ### Define an anonymous webpack chunk Source: https://github.com/googlechrome/workbox/wiki/webpack-Plugin-Info Example of a basic webpack configuration using a single entry point, resulting in an anonymous chunk. ```js const webpackConfig = { entry: './path/to/my/entry/file.js', // etc. } ``` -------------------------------- ### Register Service Worker and Inspect Cache Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-build/static/example-project-1/index.html Registers a service worker from a URL parameter, waits for installation, and logs cache entries to a global test result object. ```javascript // Helper function which returns a promise which resolves once the service worker registration // is past the "installing" state. function waitUntilInstalled(registration) { return new Promise(function (resolve, reject) { if (registration.installing) { // If the current registration represents the "installing" service worker, then wait // until the installation step (during which the resources are pre-fetched) completes // to display the file list. registration.installing.addEventListener('statechange', function (e) { if (e.target.state === 'installed') { resolve(); } else if (e.target.state === 'redundant') { reject(); } }); } else { // Otherwise, if this isn't the "installing" service worker, then installation must have been // completed during a previous visit to this page, and the resources are already pre-fetched. // So we can show the list of files right away. resolve(); } }); } const queryString = location.search.substring(1); const keyValues = queryString.split('&'); const searchParams = {}; keyValues.forEach((keyValue) => { const split = keyValue.split('='); if (split[1].indexOf('/') === split[1].length - 1) { split[1] = split[1].substring(0, split[1].length - 1); } searchParams[split[0]] = decodeURIComponent(split[1]); }); navigator.serviceWorker .register(searchParams.sw) .then((registration) => { return waitUntilInstalled(registration); }) .then(() => { return window.caches .keys() .then((keys) => { return window.caches.open(keys[0]); }) .then((cache) => { return cache.keys(); }); }) .then((entries) => { window.__testresult = { entries: entries.map((entry) => { return entry.url; }), }; }) .catch((err) => { document.body.style.color = 'red'; document.body.innerHTML = `

${err.message}

${err.stack}
`; console.error(err.message); console.error(err.stack); // This is just to help with local development so we know there is an error setTimeout(() => { window.__testresult = { error: err, }; }, 5 * 1000); }); ``` -------------------------------- ### Initialize workbox-expiration demo logic Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-expiration/index.html Sets up service worker registration, entry queue management, and event listeners for cache expiration controls. ```javascript const expireBtn = document.querySelector('.expire'); const TIMEOUT_IN_SECS = 30; const MAX_ENTRIES = 3; var entryQueue = []; const setupTimeout = (btnElement, textElement) => { textElement.textContent = `${btnElement.__workbox_timeoutCount}s`; btnElement.__workbox_timeoutId = setTimeout(() => { // TODO: FIX THIS TO TAKE FIRST ELEMENT OF CLASS LIST AND CHECK AGAIN ENTRY STACK if (entryQueue.includes(btnElement.classList[0])) { btnElement.__workbox_timeoutCount -= 1; if (btnElement.__workbox_timeoutCount > 0) { setupTimeout(btnElement, textElement); } else { textElement.textContent = `Expired (Too Old)`; } } else { textElement.textContent = `Expired (Too Many)`; } }, 1000); }; window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js').then((reg) => { for (let i = 0; i < 5; i++) { const entryBtn = document.querySelector(`.entry-${i + 1}`); const expireText = document.querySelector(`.entry-expire-${i + 1}`); entryBtn.addEventListener('click', () => { const message = { command: 'update-entry', id: i + 1, }; var arrayEntry = `entry-${i + 1}`; //If we refresh an entry that has already been added and is not expired //we reorder it to the front of the queue if (entryQueue.includes(arrayEntry)) { entryQueue.splice(entryQueue.indexOf(arrayEntry), 1); } entryQueue.push(`entry-${i + 1}`); if (entryQueue.length >= 4) { entryQueue = entryQueue.slice(MAX_ENTRIES * -1); } reg.active.postMessage(message); if (entryBtn.__workbox_timeoutId) { clearTimeout(entryBtn.__workbox_timeoutId); } entryBtn.__workbox_timeoutCount = TIMEOUT_IN_SECS; setupTimeout(entryBtn, expireText); }); } expireBtn.addEventListener('click', () => { const message = { command: 'expire-entries', }; reg.active.postMessage(message); }); }); }); ``` -------------------------------- ### Run All Tests Source: https://github.com/googlechrome/workbox/wiki/Testing Execute all tests across all Workbox packages. Ensure you are in the root directory of the project. ```shell gulp test ``` -------------------------------- ### Package Directory Structure Source: https://github.com/googlechrome/workbox/wiki/ES2015-Modules-&-Browser-Bundles Standard directory layout for a Workbox package. ```text workbox-example/ package.json README.md index.mjs _private.mjs FileName1.mjs exampleDirectory/ FileName2.mjs ``` -------------------------------- ### CSS Styles for Streams Demo Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-streams/index.html Basic styling for the demo page layout. ```css body { margin-left: 5%; font-family: 'Open Sans', sans-serif; } ol { padding-left: 20px; } li { margin-bottom: 5px; } button { margin: 20px 0; font-weight: bold; } ``` -------------------------------- ### Register and Communicate with a Service Worker Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-window/index.html Initializes a Workbox instance, registers a service worker, and sets up event listeners for lifecycle events. Requires the service worker file to be accessible at the specified path. ```javascript import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/5.0.0-beta.1/workbox-window.prod.mjs'; if ('serviceWorker' in navigator) { const wb = new Workbox('/sw.js'); wb.addEventListener('activated', (event) => { // `event.isUpdate` will be true if another version of the service // worker was controlling the page when this version was registered. if (!event.isUpdate) { console.log('Service worker activated for the first time!'); // If your service worker is configured to precache assets, those // assets should all be available now. } }); wb.addEventListener('waiting', (event) => { console.log( `A new service worker has installed, but it can't activate` + `until all tabs running the current version have fully unloaded.`, ); }); // Register the service worker after event listeners have been added. wb.register(); const message = async () => { const swVersion = await wb.messageSW({type: 'GET_VERSION'}); console.log('Service Worker version:', swVersion); }; message(); } ``` -------------------------------- ### Run Tests for a Specific Package Source: https://github.com/googlechrome/workbox/wiki/Testing To run tests for a particular Workbox package, use the `--package` flag followed by the package name. ```shell gulp test --package="workbox-something-something" ``` -------------------------------- ### Run Automated Browser Integration Tests Source: https://github.com/googlechrome/workbox/blob/v7/CONTRIBUTING.md Executes the browser-based test suite across all supported browsers. ```sh npm run gulp test_integration ``` -------------------------------- ### Implement plugins via composition Source: https://github.com/googlechrome/workbox/wiki/Styleguide Plugins should use composition rather than extending the standalone class to prevent method name collisions. ```js class SomeClassPlugin { constructor(arg1, arg2) { this._someInstance = new SomeClass(arg1, arg2); } ... } ``` ```js class SomeClassPlugin extends SomeClass { ... } ``` -------------------------------- ### Register Workbox and Lifecycle Helpers Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-window/static/index.html Exposes the Workbox class to the window object and provides a helper to wait for service worker activation and control. ```javascript import {Workbox} from '/__WORKBOX/buildFile/workbox-window'; // Expose on the global object so it can be referenced by webdriver. window.Workbox = Workbox; // Returns a promise that resolves when both the activated and controlling // events have fired on the Workbox object. window.activatedAndControlling = (wb) => { const activatedPromise = new Promise((resolve) => { wb.addEventListener('activated', () => resolve()); }); const controllingPromise = new Promise((resolve) => { wb.addEventListener('controlling', () => resolve()); }); return Promise.all([activatedPromise, controllingPromise]); }; ``` -------------------------------- ### Register Service Worker and Handle Clicks Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-strategies/index.html This script registers a service worker and sets up event listeners for buttons that trigger different network request strategies. Ensure a service worker file named 'sw.js' is present in the same directory. ```javascript const cacheOnlyEmpty = document.querySelector('.cache-only-empty-cache'); const cacheOnlyPopulated = document.querySelector( '.cache-only-populated-cache', ); const cacheFirst = document.querySelector('.cache-first'); const networkOnly = document.querySelector('.network-only'); const networkFirstValid = document.querySelector('.network-first-valid'); const networkFirstFailing = document.querySelector( '.network-first-failing', ); const staleWhileRevalidate = document.querySelector( '.stale-while-revalidate', ); window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js').then(() => { cacheOnlyEmpty.addEventListener('click', () => { fetch('cache-only-empty-cache.txt').catch(() => {}); }); cacheOnlyPopulated.addEventListener('click', () => { fetch('cache-only-populated-cache').then((response) => { return response.text(); }); }); cacheFirst.addEventListener('click', () => { fetch('cache-first.txt').then((response) => { return response.text(); }); }); networkOnly.addEventListener('click', () => { fetch('network-only.txt').then((response) => { return response.text(); }); }); networkFirstValid.addEventListener('click', () => { fetch('network-first.txt').then((response) => { return response.text(); }); }); networkFirstFailing.addEventListener('click', () => { fetch('network-first-404.txt').catch(() => {}); }); staleWhileRevalidate.addEventListener('click', () => { fetch('stale-while-revalidate.txt').then((response) => { return response.text(); }); }); }); }); ``` -------------------------------- ### Run Integration Tests Source: https://github.com/googlechrome/workbox/wiki/Testing Execute integration tests which have full access to browser and service worker APIs. ```shell gulp test-integration ``` -------------------------------- ### Implement Range Request Logic Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-range-requests/index.html Registers a service worker and sets up a click listener to fetch a specific byte range from a cached response. ```javascript const makeRequestBtn = document.querySelector('.make-range-request'); caches .open('range-requests-demo') .then((cache) => cache.put('/range-request-example', new Response('hello, world.')), ); navigator.serviceWorker.register('./sw.js').then(() => { makeRequestBtn.addEventListener('click', () => { fetch( new Request('/range-request-example', { headers: { Range: `bytes=1-4`, }, }), ) .then((response) => response.text()) .then((responseText) => { console.log(`Received response: '${responseText}'`); }); }); }); ``` -------------------------------- ### Register Service Worker and Fetch with Custom Headers Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-cacheable-response/index.html This script registers a service worker and sets up event listeners for buttons that trigger fetch requests. It demonstrates sending custom headers ('X-Is-Cacheable') to influence caching behavior. ```javascript const withGoodHeaderBtn = document.querySelector('.with-good-header'); const withBadHeaderBtn = document.querySelector('.with-bad-header'); const withoutHeaderBtn = document.querySelector('.without-header'); const DEMO_REQUEST_URL = '/api/is-response-cacheable'; window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js').then(() => { withGoodHeaderBtn.addEventListener('click', () => { fetch(DEMO_REQUEST_URL, { headers: { 'X-Is-Cacheable': true, }, }); }); withBadHeaderBtn.addEventListener('click', () => { fetch(DEMO_REQUEST_URL, { headers: { 'X-Is-Cacheable': false, }, }); }); withoutHeaderBtn.addEventListener('click', () => { fetch(DEMO_REQUEST_URL); }); }); }); ``` -------------------------------- ### Log Various Data Types with Workbox Logger Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-core/static/logger.html This snippet demonstrates logging different data types like strings, objects, arrays, and booleans using `logger.log()`, `logger.debug()`, `logger.warn()`, and `logger.error()`. Ensure your browser's developer tools are set to display all log levels, as debug logs might be hidden by default. ```javascript self.registration = { scope: 'inject-scope', }; const logger = workbox.core._private.logger; const SIMPLE_OUTPUT_TESTS = [ // String 'Hello from demo.', // Objects { foo: { bar: { baz: 'Yo.', }, }, }, ['Example of an Array', {with: 'objects'}, true, false], true, false, 1234, ]; const MULTIPLE_ARGS_OUTPUT_TESTS = [ ['Testing', 'multiple', 'strings'], ['Testing', {mixed: 'items'}, 'in', ['a', 'log']], [{this: 'is'}, 'different', 'cos', {strings: 'are'}, 'not first'], ]; const allLogBtns = [ { className: '.js-log', funcName: 'log', }, { className: '.js-debug', funcName: 'debug', }, { className: '.js-warn', funcName: 'warn', }, { className: '.js-error', funcName: 'error', }, ]; allLogBtns.forEach((logBtnDetails) => { const btnElement = document.querySelector(logBtnDetails.className); btnElement.addEventListener('click', () => { SIMPLE_OUTPUT_TESTS.forEach((output) => { logger[logBtnDetails.funcName](output); }); MULTIPLE_ARGS_OUTPUT_TESTS.forEach((output) => { logger[logBtnDetails.funcName](...output); }); console.log('\n\n'); }); }); ``` -------------------------------- ### Run Node Tests Source: https://github.com/googlechrome/workbox/wiki/Testing Execute tests that run in a Node.js environment, often utilizing mocked browser APIs. ```shell gulp test-node ``` -------------------------------- ### Cross-Module Imports Source: https://github.com/googlechrome/workbox/wiki/ES2015-Modules-&-Browser-Bundles Referencing code from other Workbox modules using direct file paths. ```javascript // Inside of a file in workbox-routing import {WorkboxError} from 'workbox-core/_private/WorkboxError.mjs'; throw new WorkboxError('error-code'); ``` -------------------------------- ### Add Unrevisioned Assets with PrecacheController Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-precaching/static/addToCacheList.html Use this method to add specific URLs to the cache list dynamically. Ensure the PrecacheController is instantiated before calling this method. ```javascript const precacheController = new workbox.precaching.PrecacheController(); const indexStringBtn = document.querySelector('.js-index-unrevisioned'); indexStringBtn.addEventListener('click', () => { precacheController.addToCacheList([ '/index.html', {url: '/example.html'}, ]); }); ``` -------------------------------- ### Run Node-based Tooling Tests Source: https://github.com/googlechrome/workbox/blob/v7/CONTRIBUTING.md Executes the test suite specifically for node-based tooling packages. ```sh npm run gulp test_node ``` -------------------------------- ### Workbox Streams Module Source: https://github.com/googlechrome/workbox/blob/v7/packages/workbox-streams/README.md Reference documentation for the workbox-streams module. ```APIDOC ## Workbox Streams Module ### Description The workbox-streams module provides utilities for creating and managing streams within a service worker, enabling the streaming of responses to the browser. ### Reference For detailed API documentation, class definitions, and method signatures, please refer to the official documentation at: https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-streams ``` -------------------------------- ### Derive asset to chunk mapping Source: https://github.com/googlechrome/workbox/wiki/webpack-Plugin-Info Logic used to build a mapping of files to their associated chunk names and hashes by iterating through compilation chunks. ```js const mapping = {}; for (const chunk of chunks) { for (const file of chunk.files) { mapping[file] = { chunkName: chunk.name, hash: chunk.renderedHash, }; } } ``` -------------------------------- ### Workbox Browser Namespace Metadata Source: https://github.com/googlechrome/workbox/wiki/Adding-a-new-package This JSON snippet shows the required metadata in a new package's package.json for Workbox. Ensure 'browserNamespace' matches the mapping in WorkboxSW.mjs. ```json { "workbox": { "browserNamespace": "workbox.somethingNew", "packageType": "browser" } } ``` -------------------------------- ### Package Import Restrictions Source: https://github.com/googlechrome/workbox/wiki/ES2015-Modules-&-Browser-Bundles Direct file imports are required to prevent unnecessary bloat in builds. ```javascript // Bad import {bar} from 'workbox-foo'; ``` ```javascript // Good import {bar} from 'workbox-foo/bar.mjs'; ``` -------------------------------- ### Conditional Module Exports Source: https://github.com/googlechrome/workbox/wiki/ES2015-Modules-&-Browser-Bundles Selecting different exports based on the build environment to optimize bundle size. ```javascript const ourExport = (process.env.NODE_ENV === 'production') ? slimExport : largeExport; export default ourExport ``` -------------------------------- ### Register Service Worker and Fetch Request Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-background-sync-demo/index.html Registers the service worker and attaches a click event listener to trigger a fetch request. ```javascript document.querySelector('.fetch').addEventListener('click', () => { fetch('example.txt'); }); navigator.serviceWorker.register('./sw.js'); ``` -------------------------------- ### Use options object for optional arguments Source: https://github.com/googlechrome/workbox/wiki/Styleguide Required fields should be positional, but an options object is preferred when expecting a wide variety of optional values. ```js new Route(matchFunc, handleFunc, options); ``` -------------------------------- ### Register Service Worker and Handle Stream Request Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-streams/index.html Registers the service worker and sets up an event listener to append an iframe that triggers a streamed response. ```javascript const makeRequestBtn = document.querySelector('.make-streams-request'); navigator.serviceWorker.register('./sw.js').then(() => { makeRequestBtn.addEventListener('click', () => { const iframe = document.createElement('iframe'); // This URL will be handled by the service worker. iframe.src = 'iframe'; document.querySelector('#iframes').appendChild(iframe); }); }); ``` -------------------------------- ### Register Service Worker with Workbox CDN Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-sw/static/index.html Use this JavaScript snippet to register a service worker that loads Workbox from a CDN. Ensure 'sw.js' is correctly configured. ```javascript navigator.serviceWorker.register('sw.js'); ``` -------------------------------- ### Dead Code Elimination with NODE_ENV Source: https://github.com/googlechrome/workbox/wiki/ES2015-Modules-&-Browser-Bundles Using environment variables to allow Rollup to strip development-only code from production bundles. ```javascript // Our source code looks like this if (process.env.NODE_ENV !== 'production') { console.log(`Hey this is super helpful but also increases file size.`); } else { console.log(`Hi.`); } // For dev builds, the above code will be outputted as { console.log(`Hey this is super helpful but also increases file size.`); } // For prod builds, the output is { console.log(`Hi.`); } ``` -------------------------------- ### Initialize Chai Expectation Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-window/static/index.html Exposes the Chai expect function to the global scope for use in test assertions. ```javascript self.expect = self.chai.expect; ``` -------------------------------- ### Create Collapsible Log Groups with Workbox Logger Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-core/static/logger.html This snippet demonstrates how to use `logger.groupCollapsed()` to create collapsible log groups, allowing for better organization of related log messages. Nested groups are also supported. Use `logger.groupEnd()` to close the current group. ```javascript const groupBtn = document.querySelector('.js-group'); groupBtn.addEventListener('click', () => { logger.groupCollapsed(`I'm the title for logger.groupCollapsed()`); const innerLog = [`I'm inside the group`, {cool: true}]; logger.debug(...innerLog); logger.log(...innerLog); logger.warn(...innerLog); logger.error(...innerLog); logger.groupCollapsed( `I'm the title for a nested logger.groupCollapsed() call`, ); const nestedLog = [`I'm doubly inside`, {superCool: true}]; logger.debug(...nestedLog); logger.log(...nestedLog); logger.warn(...nestedLog); logger.error(...nestedLog); logger.groupEnd(); logger.groupEnd(); console.log('\n\n'); }); ``` -------------------------------- ### Use destructuring for callbacks Source: https://github.com/googlechrome/workbox/wiki/Styleguide Callbacks should use destructuring to allow developers to select only the elements they need. ```js plugin.cacheDidUpdate({cacheName, request, cachedResponse, newResponse}); ``` ```js router.cacheDidUpdate(cacheName, request, cachesRedponse, newResponse); ``` ```js plugin.cacheDidUpdate({cachedResponse}) ``` ```js { cacheDidUpdate: (values) => console.log(values), } ``` -------------------------------- ### Log isURLExpired() Performance Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-expiration/static/isURLExpired.html This snippet logs the time taken by `isURLExpired()` and its result. It requires Workbox's expiration module and sets up a cache with a maximum age of 2 seconds. ```javascript self.registration = { scope: 'inject-scope', }; const CacheExpiration = workbox.expiration.CacheExpiration; const expirationManager = new CacheExpiration('cache-name', { maxAgeSeconds: 2, }); expirationManager.updateTimestamp('/', Date.now()); const test = async () => { const t0 = performance.now(); const expired = await expirationManager.isURLExpired('/'); const t1 = performance.now(); console.log( `Call to doSomething took "${t1 - t0}" milliseconds.`, expired, ); }; test(); setTimeout(test, 2000); ``` -------------------------------- ### Use positional arguments for method calls Source: https://github.com/googlechrome/workbox/wiki/Styleguide Methods called against a Workbox module should use positional arguments to avoid verbosity. ```js router.registerRoutes([...]); ``` ```js router.registerRoutes({routes: [....]}); ``` -------------------------------- ### precache.addToCacheList() Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-precaching/static/addToCacheList.html Adds unrevisioned assets to the PrecacheController's cache list. ```APIDOC ## precache.addToCacheList() ### Description Adds a list of unrevisioned assets to the PrecacheController instance for caching. ### Parameters - **entries** (Array) - Required - An array of strings or objects representing the URLs to be cached. ### Request Example ```javascript precacheController.addToCacheList([ '/index.html', {url: '/example.html'} ]); ``` ``` -------------------------------- ### Register Service Worker Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-routing/index.html Attaches a click event listener to a button to register the service worker file. ```javascript const firstBtn = document.querySelector('.install-sw'); firstBtn.addEventListener('click', () => { navigator.serviceWorker.register('./sw.js'); }); ``` -------------------------------- ### Configure Google Analytics and Service Worker Messaging Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-google-analytics/static/basic-example/index.html Initializes the dataLayer for Google Analytics and defines a helper function to communicate with the service worker via MessageChannel. ```javascript window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'UA-12345-1', {send_page_view: false}); const messageSW = (data) => { return new Promise((resolve) => { var messageChannel = new MessageChannel(); messageChannel.port1.onmessage = (evt) => resolve(evt.data); navigator.serviceWorker.controller.postMessage(data, [ messageChannel.port2, ]); }); }; ``` -------------------------------- ### Trigger Broadcast Update Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-broadcast-update-demo/index.html This JavaScript code registers a service worker and sets up an event listener to post a message to it when a button is clicked. It also listens for messages back from the service worker and logs them to the console. Ensure the service worker ('sw.js') is in the same directory. ```javascript const triggerBroadcast = document.querySelector('.trigger-broadcast'); window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js').then((reg) => { triggerBroadcast.addEventListener('click', () => { const message = { command: 'trigger-broadcast', }; reg.active.postMessage(message); }); navigator.serviceWorker.addEventListener('message', (event) => { console.log("Received a message from workbox-broadcast-update."); console.log(event.data); }); }); }); ``` -------------------------------- ### Identify known hashes from asset metadata Source: https://github.com/googlechrome/workbox/wiki/webpack-Plugin-Info Extracts unique hashes from asset metadata to build a set of known identifiers for comparison. ```js function getKnownHashesFromAssets(assetMetadata) { const knownHashes = new Set(); for (const metadata of Object.values(assetMetadata)) { knownHashes.add(metadata.hash); } return knownHashes; } const knownHashes = [ compilation.hash, compilation.fullHash, ...getKnownHashesFromAssets(filteredAssetMetadata), ].filter((hash) => !!hash); ``` -------------------------------- ### Register Service Worker and Handle Messages Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-broadcast-update/static/index.html Manually register your service worker script and set up a listener to capture messages sent from it. Ensure the service worker is registered before attempting to send messages. ```javascript window.__messages = []; navigator.serviceWorker.addEventListener('message', (event) => { window.__messages.push(event.data); }); ``` -------------------------------- ### Manage Service Worker Requests and Events Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-google-analytics/static/basic-example/index.html Handles non-GA requests, sync event dispatching, offline simulation, and request logging. ```javascript document.getElementById('send-non-ga-request').onclick = () => { fetch('https://httpbin.org/get'); }; document.getElementById('dispatch-sync-event').onclick = () => { messageSW({action: 'dispatch-sync-event'}); }; document.getElementById('simulate-offline').onclick = (evt) => { messageSW({ action: 'simulate-offline', value: evt.target.checked, }); }; document.getElementById('clear-spied-requests').onclick = (evt) => { messageSW({action: 'clear-spied-requests'}); }; document.getElementById('log-spied-requests').onclick = async (evt) => { const requests = await messageSW({action: 'get-spied-requests'}); console.log(requests); }; ``` -------------------------------- ### Register Service Worker Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-navigation-preload/index.html Registers the service worker file to enable navigation preload functionality. ```javascript window.addEventListener('load', () => { navigator.serviceWorker.register('./sw.js'); }); ``` -------------------------------- ### Register and Unregister Service Workers Source: https://github.com/googlechrome/workbox/blob/v7/demos/src/workbox-precaching/index.html Handles service worker lifecycle events triggered by button clicks to demonstrate precaching updates. ```javascript const firstBtn = document.querySelector('.install-sw-1'); const secondBtn = document.querySelector('.install-sw-2'); firstBtn.addEventListener('click', () => { navigator.serviceWorker.register('./sw-1.js'); }); secondBtn.addEventListener('click', () => { navigator.serviceWorker .getRegistration() .then((reg) => { return reg.unregister(); }) .then(() => { navigator.serviceWorker.register('./sw-2.js'); }); }); ``` -------------------------------- ### Trigger Google Analytics Events Source: https://github.com/googlechrome/workbox/blob/v7/test/workbox-google-analytics/static/basic-example/index.html Sends GA events using either image pixel or beacon transport types. ```javascript document.getElementById('send-ga-pixel').onclick = () => { gtag('event', 'pixel', { transport_type: 'image', }); }; document.getElementById('send-ga-beacon').onclick = () => { gtag('event', 'beacon', { transport_type: 'beacon', }); }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.