如何使用 FCM 服务工作者与现有的服务工作者?

3
我们正在创建一款PWA Web应用程序,目前我们正在使用sw-precache库生成服务工作者文件,并且它的功能正常。现在,我们已经添加了FCM服务工作者来监听离线状态下的传入消息,但它会覆盖我们现有的服务工作者。
那么,我们该如何将Firebase服务工作者与使用sw-precache生成的现有服务工作者集成起来?
我尝试了几种方法,当前代码:
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js').then((registration) => {
        console.log('Service Worker registered');
    }).catch(function (err) {
        console.log('Service Worker registration failed: ', err);
    });

    navigator.serviceWorker.register('/firebase-messaging-sw.js', { scope: '/firebase-cloud-messaging-push-scope' }).then(function (registration) {
         console.log('f Service Worker registered');
     }).catch(function (err) {
         console.log('f Service Worker registration failed: ', err);
     });
}

更新1:我也尝试了useServiceWorker(registration),它注册了主要的服务工作者,但是当我在我的服务中初始化Firebase时,它期望firebase-messaging-sw.js被加载,所以在控制台中抛出了一些错误。

服务代码:

import * as firebase from 'firebase';
import { isPlatformBrowser } from '@angular/common';

@Injectable()
export class MessagingService {   
  messaging;

  constructor(
    @Inject(PLATFORM_ID) private _platformId: Object, ) {
    if (isPlatformBrowser(this._platformId)) {
      var config = {
        messagingSenderId: "XXXXXXXX"
      };

      firebase.initializeApp(config);
      this.messaging = firebase.messaging();
    }
  }

  //  ......

}

控制台错误:

enter image description here

enter image description here

我也尝试了以下答案,但没有成功:https://dev59.com/WqTja4cB1Zd3GeqPHtLT#46171748


更新2: 最后添加useServiceWorker(registration)和一个空的firebase-messaging-sw.js 文件,两个服务工作者都已注册,但缓存不起作用。


/service-worker.js 提供的路径不正确。我已经将路径提供为 ${process.env.PUBLIC_URL}/firebase-messaging-sw.js,其中 firebase-messaging-sw.js 位于创建 React 应用程序的 public 文件夹中。 - haripcce
2个回答

6
为了完全控制 sw.js 和推送通知,使用 useServiceWorker 是非常有用的。
请参考此文档:useServiceWorker(registration)
   /------index.html------/
    var config = {
        apiKey: "xxxxxxxxxxxx",
        authDomain: "xxxxxxxxxxxx",
        databaseURL: "xxxxxxxxxxxx",
        projectId: "xxxxxxxxxxxx",
        storageBucket: "xxxxxxxxxxxx",
        messagingSenderId: "xxxxxxxxxxxx"
    };
    firebase.initializeApp(config);
    var messaging = firebase.messaging();

navigator.serviceWorker.register('service-worker.js')
.then((registration) => {
  messaging.useServiceWorker(registration);


});

我也尝试过这个......但是当我在我的服务中尝试初始化Firebase时,它显示服务工作程序注册失败..... - Pranav C Balan
你能分享一下项目目录中文件结构的截图吗? - Tushar Acharekar
在生产环境中,两个服务工作者将位于同一个目录下,即/dist文件夹。 - Pranav C Balan
firebase-messaging-sw.js 是 FCM 推送通知所必需的文件,我认为你的问题根源是 text/html 的 MIME 类型,尝试删除该错误。 - Tushar Acharekar
你是否知道,SW 只在 localhosthttps 上注册...? - Tushar Acharekar
显示剩余7条评论

3

在app.module.ts中,或者你可以将以constructor(sw...)开头的代码片段放入一个服务文件中,在到达某个延迟加载的特性模块时初始化该服务。

import * as firebase from 'firebase';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ServiceWorkerModule.register('/ngsw-worker.js', {enabled: environment.production}),
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(swPush: SwPush) {
    if (swPush.isEnabled) {
      navigator.serviceWorker
        .ready
        .then((registration) => firebase.messaging().useServiceWorker(registration));
    }
  }
}

在 angular-cli.json 文件中确保有 firebase-messaging-sw.js。

{
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico",
        "manifest.json",
        "firebase-messaging-sw.js"
      ],
      "index": "index.html",
      "main": "main.ts",
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      },
      "serviceWorker": true
    }
  ]
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接