@3m1/service-worker-updater 中文文档教程

发布于 3年前 浏览 38 项目主页 更新于 3年前

NPM 贡献者契约 测试 Coverage BundlePhobia 缩小尺寸 BundlePhobia 最小压缩尺寸 BundlePhobia 依赖计数 BundlePhobia 摇树支持 每月下载 Dependabot Active DeepSource

@3m1/service-worker-updater

管理 Create React App 的 Service Worker 更新

如果您选择加入 register index.jsserviceWorkerRegistration回调-progressive-web-app/">Create React APP 的 PWA 版本,您可能希望允许您的用户在检测到新的 service worker 后更新应用程序。

How it works

通常,浏览器每隔几天检查一次 PWA 的新服务工作者版本,或者每当用户重新加载页面时检查一次。 但是重新加载页面并不一定会更新 service worker。 由于管理 service worker 的代码通常在 React 组件树之外,检测到新 service worker 的消息 需要通过 props 或上下文之外的另一种机制传递。 在这里,我们使用通过 document 触发的事件,该事件之前已添加了一个侦听器。 添加侦听器的组件位于 React 的组件树内,并接收并保存resgistration 对象以供以后在onLoadNewServiceWorkerAccept 回调中使用。

Install

NPM

npm install --save @3m1/service-worker-updater

Yarn

yarn add @3m1/service-worker-updater

Usage

该库由两部分组成:

onServiceWorkerUpdate

要添加到 index.js 上的 serviceWorkerRegistration.register 调用的回调。 此步骤是强制性的,否则消息将不会到达您的内部组件。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorkerRegistration from './serviceWorkerRegistration'
import { onServiceWorkerUpdate } from '@3m1/service-worker-updater'

// Render the App
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://cra.link/PWA
serviceWorkerRegistration.register({
  onUpdate: onServiceWorkerUpdate
})

// ...

如果您已经在使用 onUpdate 回调,则需要在其中添加此回调:

serviceWorkerRegistration.register({
  onUpdate: (registration) => {
    // Your code goes here
    // ...
    // Then, call this callback:
    onServiceWorkerUpdate(registration)
  }
})

withServiceWorkerUpdater

HOC 包装一个将接收 2 个额外 props 的组件:

  • 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.
  • 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.
import React from 'react'
import {
  withServiceWorkerUpdater,
  ServiceWorkerUpdaterProps
} from '@3m1/service-worker-updater'

const Updater = (props: ServiceWorkerUpdaterProps) => {
  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props
  return newServiceWorkerDetected ? (
    <>
      New version detected.
      <button onClick={onLoadNewServiceWorkerAccept}>Update!</button>
    </>
  ) : null // If no update is available, render nothing
}

export default withServiceWorkerUpdater(Updater)

对于非 Typescript 项目,请使用以下片段:

import React from 'react'
import { withServiceWorkerUpdater } from '@3m1/service-worker-updater'

const Updater = (props) => {
  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props
  return newServiceWorkerDetected ? (
    <>
      New version detected.
      <button onClick={onLoadNewServiceWorkerAccept}>Update!</button>
    </>
  ) : null // If no update is available, render nothing
}

export default withServiceWorkerUpdater(Updater)

发送给服务工作人员的消息是 {type: 'SKIP_WAITING'},这是 Create React APP 的 PWA 版本 期望启动其 self.skipWaiting() 方法。 如果您有不同的 service worker 配置,您可以使用第二个可选参数在此处更改它:

export default withServiceWorkerUpdater(Updater, {
  message: { myCustomType: 'SKIP_WAITING' }
})

在重新加载页面之前,'Controller loaded' 将使用 console.log 记录>。 如果您想更改它,请这样做:

export default withServiceWorkerUpdater(Updater, {
  log: () => console.warn('App updated!')
})

Persistence

当检测到新的服务工作者时,将触发一个事件。 如果刷新应用程序,则不会再次触发该事件,因此您将无法再通知用户服务工作者更新。 这个包以 PersistenceService 的形式提供了解决方案。

持久性服务被注入到组件中并处理刷新后的状态持久化。 该软件包带有一个默认的基于本地存储的持久化服务。 它可以这样使用:

import { LocalStoragePersistenceService } from '@3m1/service-worker-updater'

const Updater = () => {
  /* Your updater component code */
}

export default withServiceWorkerUpdater(Updater, {
  persistenceService: new LocalStoragePersistenceService('myApp')
})

您可以通过遵守 PersistenceService 接口定义您自己的基于其他机制的持久层:

import { PersistenceService } from '@3m1/service-worker-updater'

class YourPersistenceService implements PersistenceService {
  setUpdateIsNeeded(): void {}

  clear(): void {}

  isUpdateNeeded(): boolean {
    return false
  }
}

:trophy: Thanks to

See also

  • 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.
  • Service Worker Updater - React Hook & HOC: This package provides React hook and HOC to check for service worker updates.
  • @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.

License

GPL-3.0-or-later © github.com/emibcn

NPM Contributor Covenant Test Coverage BundlePhobia Minified Size BundlePhobia Minzipped Size BundlePhobia Dependency Count BundlePhobia Tree-shaking support Monthly Downloads Dependabot Active DeepSource

@3m1/service-worker-updater

Manage Create React App's Service Worker update

If you have opted-in for the register callback of serviceWorkerRegistration in the index.js of the PWA version of Create React APP, you probably want to allow your users to update the application once a new service worker has been detected.

How it works

Usually, 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.

Install

NPM

npm install --save @3m1/service-worker-updater

Yarn

yarn add @3m1/service-worker-updater

Usage

This library is composed by 2 parts:

onServiceWorkerUpdate

Callback 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.

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorkerRegistration from './serviceWorkerRegistration'
import { onServiceWorkerUpdate } from '@3m1/service-worker-updater'

// Render the App
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://cra.link/PWA
serviceWorkerRegistration.register({
  onUpdate: onServiceWorkerUpdate
})

// ...

If you are already using the onUpdate callback, you need to add this callback in there:

serviceWorkerRegistration.register({
  onUpdate: (registration) => {
    // Your code goes here
    // ...
    // Then, call this callback:
    onServiceWorkerUpdate(registration)
  }
})

withServiceWorkerUpdater

HOC to wrap a component which will receive 2 extra props:

  • 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.
  • 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.
import React from 'react'
import {
  withServiceWorkerUpdater,
  ServiceWorkerUpdaterProps
} from '@3m1/service-worker-updater'

const Updater = (props: ServiceWorkerUpdaterProps) => {
  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props
  return newServiceWorkerDetected ? (
    <>
      New version detected.
      <button onClick={onLoadNewServiceWorkerAccept}>Update!</button>
    </>
  ) : null // If no update is available, render nothing
}

export default withServiceWorkerUpdater(Updater)

For non Typescript projects, use the following snippet:

import React from 'react'
import { withServiceWorkerUpdater } from '@3m1/service-worker-updater'

const Updater = (props) => {
  const { newServiceWorkerDetected, onLoadNewServiceWorkerAccept } = props
  return newServiceWorkerDetected ? (
    <>
      New version detected.
      <button onClick={onLoadNewServiceWorkerAccept}>Update!</button>
    </>
  ) : null // If no update is available, render nothing
}

export default withServiceWorkerUpdater(Updater)

The message sent to the service worker is {type: 'SKIP_WAITING'}, which is the one the PWA version of Create React 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:

export default withServiceWorkerUpdater(Updater, {
  message: { myCustomType: 'SKIP_WAITING' }
})

Just before reloading the page, 'Controller loaded' will be logged with console.log. If you want to change it, do it so:

export default withServiceWorkerUpdater(Updater, {
  log: () => console.warn('App updated!')
})

Persistence

When 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.

The 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:

import { LocalStoragePersistenceService } from '@3m1/service-worker-updater'

const Updater = () => {
  /* Your updater component code */
}

export default withServiceWorkerUpdater(Updater, {
  persistenceService: new LocalStoragePersistenceService('myApp')
})

You can define your own persistence layer based on other mechanisms by adhering to the PersistenceService interface:

import { PersistenceService } from '@3m1/service-worker-updater'

class YourPersistenceService implements PersistenceService {
  setUpdateIsNeeded(): void {}

  clear(): void {}

  isUpdateNeeded(): boolean {
    return false
  }
}

:trophy: Thanks to

See also

  • 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.
  • Service Worker Updater - React Hook & HOC: This package provides React hook and HOC to check for service worker updates.
  • @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.

License

GPL-3.0-or-later © github.com/emibcn

更多

友情链接

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文