workbox-webpack-plugin和Angular。如何在Angular中收听广播更新事件

Ton*_*nio 5 broadcast webpack angular workbox workbox-webpack-plugin

我正在尝试在我的Angular Application中使用service-worker。它是使用webpack构建的。

我使用workbox-webpack-plugin。我想为我的GET API调用提供表单缓存,并在后台更新数据。

为此,我将选项runtimeCaching与处理程序一起使用staleWhileRevalidate有关GenerateSW插件的更多详细信息,请参见此处

这是我在webpack.config.js中的配置:

  new GenerateSW({
    // importWorkboxFrom: 'local',
    clientsClaim: true,
    skipWaiting: true,
    navigateFallback: '/index.html',
    runtimeCaching: [
      {
        // Match any same-origin request that contains 'api'.
        urlPattern: /https:\/\/api.*/,
        handler: 'staleWhileRevalidate',
        options: {
          cacheName: 'api',
          broadcastUpdate: {
            channelName: 'api-updates',
          },
          // Add in any additional plugin logic you need.
          plugins: [],
        },
      }
    ]
  }),
Run Code Online (Sandbox Code Playgroud)

根据本文档,当缓存更新时,我应该能够收到一个事件(我想向用户显示某些内容,以便他可以刷新数据)。

接收数据的代码如下所示:

export class AppComponent implements OnInit {

  public ngOnInit() {
    console.log( 'AppComponent - ngOnInit' );

    const updatesChannel = new BroadcastChannel('api-updates');
    updatesChannel.addEventListener('message', async (event) => {
      console.log('Event received');
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

我将此代码放在我的Angular组件之一中,即使我确定缓存已更新,也从未被调用。

我认为这可能与Angular中更改检测的工作方式有关(如此问题中所述),但我不确定如何解决它。

是否有人设法成功收听了来自Angular组件的广播事件?

seb*_*ier 2

很难通过工作箱文档找到解决方案。

在启动应用程序时,您可以注册到 workbox serviceworker 并onupdatefound在检测到更改并加载它时覆盖更新 UI:

if (process.env.NODE_ENV != "development" && "serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("/service-worker.js")
      .then(registration => {
        registration.onupdatefound = event => {
          console.log("An update has been detected. Workbox will now download the newest version, then send a notification.");
        };
      })
      .catch(registrationError => {
        console.log("SW registration failed: ", registrationError);
      });
  });
}
Run Code Online (Sandbox Code Playgroud)

当工作箱检测到当前缓存版本与服务器上存储的版本(以散列形式存储在precache-manifest.d6104197c4431d9f111e4c4f0bdf858d.js)之间的差异时,会触发此操作。

为了检测收到并准备加载的文件的实际更新,我无法broadcastUpdate按照文档中所述进行选项,因此受到它的启发,我在 webpack 和我的应用程序之间实现了 MessageChannel。

在网页包中:

new WorkboxPlugin.GenerateSW({
      // these options encourage the ServiceWorkers to get in there fast
      // and not allow any straggling 'old' SWs to hang around
      clientsClaim: true,
      skipWaiting: true,
      include: [
        /\.html$/,
        /\.js$/,
        /\.jpg$/,
        /\.svg$/,
        /\.png$/,
        /\.json$/,
        /\.xml$/
      ],
      runtimeCaching: [
        {
          urlPattern: /./,
          handler: "StaleWhileRevalidate",
          options: {
            // Add in any additional plugin logic you need.
            plugins: [
              {
                cacheDidUpdate: event => {
                  clients.matchAll().then(clients => {
                    clients.forEach(client => {
                      var msg_chan = new MessageChannel();
                      client.postMessage("APP_UPDATE", [msg_chan.port2]);
                    });
                  });
                }
              }
            ]
          }
        }
      ]
    })
Run Code Online (Sandbox Code Playgroud)

这将从“我不知道”的频道发送一条消息。然后我们可以在应用程序中的该通道上添加一个监听器来触发 ou UI。

在应用程序中:

if ("serviceWorker" in navigator) {
  navigator.serviceWorker.addEventListener("message", event => {
    if (event.data == "APP_UPDATE") {
      dispatch(AppActions.cacheDidUpdate());
    }
  });
}
Run Code Online (Sandbox Code Playgroud)