CoatneyDev
CoatneyDev

Reputation: 21

Push Notifications, Multiple Service Workers? Angular Ionic 5 PWA for Web/Android/IOS and Firebase

I'm having trouble with my Ionic/Angular Capacitor PWA. I need to set up PUSH NOTIFICATIONS for Web, Android and IOS but right now just focusing on Web.

I have Angular app set up to ask the user permission for notifications. I store a token in firestore using the firebase uid they logged in with when they respond 'YES'. I have firebase functions that are supposed to fire onCreate of a particular document type when it is created in the firestore db.

My problem is the next step. Everywhere I look I am supposed to set up a service worker to handle the notifications. But I already HAVE one (PWA) and I don't know how to set up another service worker that wont mess up the PWA sw.

Somehow I need to make this work cross-platform. I will need to make it work for Web right now but later for android/ionic too.

Can I use multiple service workers without causing problems? How? How will it change when I do Android/IOS implementation? Is there a resource you could point me to?

Thanks in advance

Upvotes: 1

Views: 2567

Answers (1)

Sergey Rudenko
Sergey Rudenko

Reputation: 9235

In a modern Angular (8+) application the service worker is generated at build time and its configuration is done via ngsw-config.json file that resides in the root folder of your project.

In your case you need to ensure your project's service worker features firebase imports and incoming notification messages handler functions. For that one strategy can be:

  • create another combined-service-worker.js file
  • make it import angular's service worker using importScripts('ngsw-worker.js');
  • in your app.module.ts point ServiceWorkerModule to leverage combined-service-worker.js excplicitely

Here is how your combined-service-worker.js can look like:

// IMPORT ANGULAR'S SW:
importScripts('ngsw-worker.js');

// FIREBASE PART:
if (ServiceWorkerRegistration && "pushManager" in ServiceWorkerRegistration.prototype) {

    importScripts('https://www.gstatic.com/firebasejs/7.13.1/firebase-app.js');
    importScripts('https://www.gstatic.com/firebasejs/7.13.1/firebase-messaging.js');

    initializeFirebaseCloudMessaging();

    const messaging = firebase.messaging();

    enableBackGroundMessages();

    function initializeFirebaseCloudMessaging() {

        const FIREBASE_CONFIG = {
            // apiKey: ...
            // etc config for your firebase project
        }

        firebase.initializeApp(FIREBASE_CONFIG);

    };

    function enableBackGroundMessages() {
        messaging.setBackgroundMessageHandler((payload) => {
            const notificationOptions = {
                body: payload.message,
                icon: 'assets/img/mstile-150x150.png'
            };
            return self.registration.showNotification("Morphistic", notificationOptions);
        });
    };

};

You can create this file in your root folder and configure your project's angular.json to treat it as "asset":

       "assets": [
          "src/favicon.ico",
          "src/robot.txt",
          "src/manifest.json",
          "src/combined-service-worker.js",
          {
            "glob": "**/*",
            "input": "src/assets",
            "output": "assets"
          },
          {
            "glob": "**/*.svg",
            "input": "node_modules/ionicons/dist/ionicons/svg",
            "output": "./svg"
          }
        ],

This will ensure the combined-service-worker.js will make it into the folder after build.

Now in your app.module.ts you can explicitly set this worker as the one app needs to activate:

...
import { ServiceWorkerModule } from '@angular/service-worker';
...

@NgModule({
  declarations: [
    AppComponent,
    MorphBarComponent
  ],
  imports: [
    IonicModule.forRoot({
      mode: 'ios'
    }),
    AppRoutingModule,
    PipesModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule,
    IonicStorageModule.forRoot(),
    ServiceWorkerModule.register('combined-service-worker.js', { enabled: true, registrationStrategy: 'registerImmediately' }),
    BrowserModule,
    HammerModule,
    AngularFireModule.initializeApp(ENV.FIREBASE_CONFIG),
    AngularFireMessagingModule
  ],

Later one when you will get hybrid builds for iOS/Android, you can tweak activation strategies such that if the Platform is 'hybrid' you skip service worker registration completely.

Upvotes: 2

Related Questions