{"id":20183002,"url":"https://github.com/emibcn/service-worker-updater","last_synced_at":"2025-04-10T05:24:07.286Z","repository":{"id":36966577,"uuid":"355964755","full_name":"emibcn/service-worker-updater","owner":"emibcn","description":"Manage Create React App's Service Worker update","archived":false,"fork":false,"pushed_at":"2024-04-12T07:01:33.000Z","size":6145,"stargazers_count":18,"open_issues_count":2,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-12T14:28:53.886Z","etag":null,"topics":["hacktoberfest","javascript","javascript-library","npm-package","pwa","react","react-component","reactjs","service-worker","service-worker-lifecycle","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@3m1/service-worker-updater","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emibcn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-04-08T15:42:03.000Z","updated_at":"2024-04-15T07:55:53.193Z","dependencies_parsed_at":"2024-01-18T09:47:30.263Z","dependency_job_id":"cd66a63c-6466-4268-9991-8633adf0e4d8","html_url":"https://github.com/emibcn/service-worker-updater","commit_stats":{"total_commits":342,"total_committers":7,"mean_commits":"48.857142857142854","dds":0.2222222222222222,"last_synced_commit":"bad4c733a6e91fd1d40a0686360a59685e64e14c"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emibcn%2Fservice-worker-updater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emibcn%2Fservice-worker-updater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emibcn%2Fservice-worker-updater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emibcn%2Fservice-worker-updater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emibcn","download_url":"https://codeload.github.com/emibcn/service-worker-updater/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248161743,"owners_count":21057643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","javascript","javascript-library","npm-package","pwa","react","react-component","reactjs","service-worker","service-worker-lifecycle","typescript"],"created_at":"2024-11-14T02:43:40.902Z","updated_at":"2025-04-10T05:24:07.260Z","avatar_url":"https://github.com/emibcn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![NPM](https://img.shields.io/npm/v/@3m1/service-worker-updater.svg)](https://www.npmjs.com/package/@3m1/service-worker-updater)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://github.com/emibcn/service-worker-updater/blob/main/CODE_OF_CONDUCT.md)\n[![Test](https://github.com/emibcn/service-worker-updater/actions/workflows/test.js.yml/badge.svg)](https://github.com/emibcn/service-worker-updater/actions/workflows/test.js.yml)\n[![Coverage](https://raw.githubusercontent.com/emibcn/service-worker-updater/badges/main/test-coverage.svg)](https://github.com/emibcn/service-worker-updater/actions/workflows/test.js.yml)\n[![BundlePhobia Minified Size](https://badgen.net/bundlephobia/min/@3m1/service-worker-updater)](https://bundlephobia.com/result?p=@3m1/service-worker-updater)\n[![BundlePhobia Minzipped Size](https://badgen.net/bundlephobia/minzip/@3m1/service-worker-updater)](https://bundlephobia.com/result?p=@3m1/service-worker-updater)\n[![BundlePhobia Dependency Count](https://badgen.net/bundlephobia/dependency-count/@3m1/service-worker-updater)](https://bundlephobia.com/result?p=@3m1/service-worker-updater)\n[![BundlePhobia Tree-shaking support](https://badgen.net/bundlephobia/tree-shaking/@3m1/service-worker-updater)](https://bundlephobia.com/result?p=@3m1/service-worker-updater)\n[![Monthly Downloads](https://badgen.net/npm/dm/@3m1/service-worker-updater)](https://www.npmjs.com/package/@3m1/service-worker-updater)\n[![Dependabot Active](https://badgen.net/github/dependabot/emibcn/service-worker-updater)](https://github.com/emibcn/service-worker-updater/blob/main/.github/dependabot.yml)\n[![DeepSource](https://deepsource.io/gh/emibcn/service-worker-updater.svg/?label=active+issues\u0026show_trend=true\u0026token=lpel9ySTZydoTIbv0WGSfgOc)](https://deepsource.io/gh/emibcn/service-worker-updater/?ref=repository-badge)\n\n# @3m1/service-worker-updater\n\n\u003e Manage Create React App's Service Worker update\n\nIf you have opted-in for the `register` callback of `serviceWorkerRegistration` in the `index.js` of the [PWA version of Create React APP](https://create-react-app.dev/docs/making-a-progressive-web-app/), you probably want to allow your users to update the application once a new service worker has been detected.\n\n## How it works\n\nUsually, browsers check for a new service worker version of a PWA every few days, or whenever the user reloads the page. But reloading the page does not necessarily updates the service worker. As the code managing the service worker is usually outside the React components tree, the message of a _new service worker detected_ needs to be passed through another mechanism than props or contexts. Here, we use an event triggered over `document`, which will previously have been added a listener. The component that adds the listener **is** inside the React's components tree, and receives and saves the `resgistration` object for later use in the `onLoadNewServiceWorkerAccept` callback.\n\n## Install\n\n### NPM\n\n```bash\nnpm install --save @3m1/service-worker-updater\n```\n\n### Yarn\n\n```bash\nyarn add @3m1/service-worker-updater\n```\n\n## Usage\n\nThis library is composed by 2 parts:\n\n### `onServiceWorkerUpdate`\n\nCallback to be added to the `serviceWorkerRegistration.register` call on your `index.js`. **This step is mandatory**, or the message will not arrive to your inner component.\n\n```tsx\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport App from './App'\nimport * as serviceWorkerRegistration from './serviceWorkerRegistration'\nimport { onServiceWorkerUpdate } from '@3m1/service-worker-updater'\n\n// Render the App\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n    \u003cApp /\u003e\n  \u003c/React.StrictMode\u003e,\n  document.getElementById('root')\n)\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://cra.link/PWA\nserviceWorkerRegistration.register({\n  onUpdate: onServiceWorkerUpdate\n})\n\n// ...\n```\n\nIf you are already using the `onUpdate` callback, you need to add this callback in there:\n\n```tsx\nserviceWorkerRegistration.register({\n  onUpdate: (registration) =\u003e {\n    // Your code goes here\n    // ...\n    // Then, call this callback:\n    onServiceWorkerUpdate(registration)\n  }\n})\n```\n\n### `withServiceWorkerUpdater`\n\nHOC to wrap a component which will receive 2 extra `props`:\n\n- `newServiceWorkerDetected`: boolean indicating if a new version of the service worker has been detected. If `true`, you should offer the user some way to update the app.\n- `onLoadNewServiceWorkerAccept`: a callback which needs to be called once the user accepts to update to the new Service Worker. You choose what actions needs to be taken by the user to update the service worker (a button, a link, a countdown, ...). During its execution, **the page will be reloaded** in order to use the newly activated service worker. **WARNING!** Make sure all unsaved changes are saved before executing it.\n\n```tsx\nimport React from 'react'\nimport {\n  withServiceWorkerUpdater,\n  ServiceWorkerUpdaterProps\n} from '@3m1/service-worker-updater'\n\nconst Updater = (props: ServiceWorkerUpdaterProps) =\u003e {\n  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props\n  return newServiceWorkerDetected ? (\n    \u003c\u003e\n      New version detected.\n      \u003cbutton onClick={onLoadNewServiceWorkerAccept}\u003eUpdate!\u003c/button\u003e\n    \u003c/\u003e\n  ) : null // If no update is available, render nothing\n}\n\nexport default withServiceWorkerUpdater(Updater)\n```\n\nFor non Typescript projects, use the following snippet:\n\n```jsx\nimport React from 'react'\nimport { withServiceWorkerUpdater } from '@3m1/service-worker-updater'\n\nconst Updater = (props) =\u003e {\n  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props\n  return newServiceWorkerDetected ? (\n    \u003c\u003e\n      New version detected.\n      \u003cbutton onClick={onLoadNewServiceWorkerAccept}\u003eUpdate!\u003c/button\u003e\n    \u003c/\u003e\n  ) : null // If no update is available, render nothing\n}\n\nexport default withServiceWorkerUpdater(Updater)\n```\n\nThe message sent to the service worker is `{type: 'SKIP_WAITING'}`, which is the one the [PWA version of Create React APP](https://create-react-app.dev/docs/making-a-progressive-web-app/) expects in order to launch its `self.skipWaiting()` method. If you have a different service worker configuration, you can change it here using the second optional argument:\n\n```tsx\nexport default withServiceWorkerUpdater(Updater, {\n  message: { myCustomType: 'SKIP_WAITING' }\n})\n```\n\nJust before reloading the page, `'Controller loaded'` will be logged with `console.log`. If you want to change it, do it so:\n\n```tsx\nexport default withServiceWorkerUpdater(Updater, {\n  log: () =\u003e console.warn('App updated!')\n})\n```\n\n## Persistence\n\nWhen a new service worker is detected an event is fired. If the app is refreshed, the event is not fired again so you'll no longer be able to notify users about service worker updates. This package provides a solution to that in the form of a `PersistenceService`.\n\nThe persistence service is injected into the component and handles persisting the state after refresh. The package comes with a default persistence service based on local storage. It can be used thus:\n\n```tsx\nimport { LocalStoragePersistenceService } from '@3m1/service-worker-updater'\n\nconst Updater = () =\u003e {\n  /* Your updater component code */\n}\n\nexport default withServiceWorkerUpdater(Updater, {\n  persistenceService: new LocalStoragePersistenceService('myApp')\n})\n```\n\nYou can define your own persistence layer based on other mechanisms by adhering to the `PersistenceService` interface:\n\n```tsx\nimport { PersistenceService } from '@3m1/service-worker-updater'\n\nclass YourPersistenceService implements PersistenceService {\n  setUpdateIsNeeded(): void {}\n\n  clear(): void {}\n\n  isUpdateNeeded(): boolean {\n    return false\n  }\n}\n```\n\n## :trophy: Thanks to\n\n- [\u003cimg align=\"center\" width=\"30px\" height=\"30px\" src=\"https://avatars.githubusercontent.com/u/2166114?s=40\u0026v=4\" /\u003e](https://github.com/aeharding) [Alexander Harding](https://github.com/aeharding) for [translating the library into Typescript](https://github.com/emibcn/service-worker-updater/pull/55).\n\n## See also\n\n- [React Service Worker](https://www.npmjs.com/package/@medipass/react-service-worker): A headless React component that wraps around the Navigator Service Worker API to manage your service workers. Inspired by Create React App's service worker registration script.\n- [Service Worker Updater - React Hook \u0026 HOC](https://www.npmjs.com/package/service-worker-updater): This package provides React hook and HOC to check for service worker updates.\n- [@loopmode/cra-workbox-refresh](https://www.npmjs.com/package/@loopmode/cra-workbox-refresh): Helper for `create-react-app` v2 apps that use the workbox service worker. Displays a UI that informs the user about updates and recommends a page refresh.\n\n## License\n\nGPL-3.0-or-later © [github.com/emibcn](https://github.com/github.com/emibcn)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femibcn%2Fservice-worker-updater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femibcn%2Fservice-worker-updater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femibcn%2Fservice-worker-updater/lists"}