web-dev-qa-db-ja.com

Create React AppでskipWaitingを実装する方法は?

新しいサービスワーカーが利用可能で待機しているときに、ユーザーがその場で更新できるようにしたいですか?新しいアップデートが利用可能になったときにポップアップを表示することはできますが、その場でアップデートを強制するボタンを追加したいと思います。これはskipWaitingを呼び出すことで達成できることを理解していますが、Create React Appを使用して実装する方法がわかりません。これを達成できる人がいますか?助けていただけませんか。ありがとうございます。

10
user10532439

https://github.com/bbhlondon/cra-append-sw というパッケージを使用して、トリガーskipWaitingを呼び出す次のコードを追加しました。

self.addEventListener('message', event => {
  if (event.data === 'skipWaiting') {
    self.skipWaiting();
  }
});
1
user10532439

serviceWorker.jsファイルでこのコードを見つけることができます

if (config && config.onUpdate) {
    config.onUpdate(registration);
 }

したがって、config.onUpdate関数を実装します

ファイルを作成swConfig.js

export default {
 onUpdate: registration => {
   registration.unregister().then(() => {
   window.location.reload()
 })
},
onSuccess: registration => {
  console.info('service worker on success state')
  console.log(registration)
 },
}

index.jsで、実装機能をserviceWorkerに送信します

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import swConfig from './swConfig'

ReactDOM.render(<App />, 
document.getElementById('root'));
serviceWorker.register(swConfig);

このリポジトリをチェックしてください https://github.com/wgod58/create_react_app_pwaupdate

8
ZedPai

CRA build\service-worker.jsファイル(v3 plus)にskipWaitingを処理するコードが含まれるようになりました:

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

レジスタ関数serviceWorker.jsで呼び出されるファイルindex.jsが設定パラメータを受け入れるようになりました:

serviceWorker.register({
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if (event.target.state === "activated") {
          window.location.reload()
        }
      });
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
    }
  }
});

これは待機をスキップし、更新が適用されるとページを更新します。

6
user1843640

私はそれが答えられたことを知っていますが、もちろんワークボックス以外の追加のパッケージを必要としないソリューションを見つけました。

package.jsonで:

_"build": "react-scripts build && node ./src/serviceWorkerBuild"
_

serviceWorkerBuild.js

_const workboxBuild = require('workbox-build');

// NOTE: This should be run *AFTER* all your assets are built
const buildSW = () => {
  // This will return a Promise
  return workboxBuild.injectManifest({
    swSrc: 'src/serviceWorkerRules.js',
    swDest: 'build/sw.js',
    globDirectory: 'build',
    globPatterns: [
      '**\/*.{js,css,html,png}',
    ]
  }).then(({count, size, warnings}) => {
    // Optionally, log any warnings and details.
    warnings.forEach(console.warn);
    console.log(`${count} files will be precached, totaling ${size} bytes.`);
  });
};

buildSW();
_

およびserviceWorkerRules.jsルールを追加できる場所:

_importScripts(
    'https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js'
);
/* global workbox */
if (workbox) {
    console.log('Workbox is loaded');

  self.addEventListener('install', event => {
    self.skipWaiting();
  });

    /* injection point for manifest files.  */
    workbox.precaching.precacheAndRoute([]);

/* custom cache rules*/
workbox.routing.registerNavigationRoute('/index.html', {
    blacklist: [/^\/_/, /\/[^\/]+\.[^\/]+$/],
    });

workbox.routing.registerRoute(
    /\.(?:png|gif|jpg|jpeg|svg)$/,
    workbox.strategies.cacheFirst({
        cacheName: 'images',
        plugins: [
            new workbox.expiration.Plugin({
                maxEntries: 60,
                maxAgeSeconds: 5 * 24 * 60 * 60, // 5 Days
            }),
        ],
    }),
    );
_

また、78行目のwindow.location.reload();serviceWorker.jsに追加します。

1
Ristic

@ user10532439からの回答がうまくいきませんでした。私は https://github.com/bbhlondon/cra-append-sw を使用して追加しました

// @ts-ignore
workbox.skipWaiting();

// @ts-ignore
workbox.clientsClaim();

に加えて

"build": "react-scripts build && cra-append-sw -s ./src/custom-sw.js",
1
P4ul

ServiceWorkerのインストールイベントでskipWaitingメソッドを呼び出す必要があります。 Service WorkerはUI/Reactコードから分離されています。つまり、実際に反応することとは何の関係もありません。

現在、インストールイベントコードを独自のメソッドにリファクタリングするパターンがあるため、サービスワーカーは次のようになります。

self.addEventListener( "install", function ( event ) {

    event.waitUntil( installServiceWorker() );

} );

function installServiceWorker() {

    self.skipWaiting();
// do stuff here like pre-caching site core assets
//most likely returning a promise

}

また、キャッシュされたアセットをアクティブなUIと同期する必要がある場合は、skipWaitingを呼び出さないでください。 Service Workerが更新されており、UIが壊れる可能性がある場合は、skipWaitingを呼び出さないでください。代わりに、ユーザーがページを更新するまで待ちます。たとえば、メッセージングインフラストラクチャを使用して、更新が利用可能であることをユーザーに通知し、例として更新することができます。

0
Chris Love