I wanted to explore the process of sending server messages to PWA apps. In this blog post, I will guide you through the steps I took to set up this functionality using Vite.

cloudflare home ddns

Project structure


├── public
│   ├── firebase-messaging-sw.js
│   ├── logo-48-48.png
│   ├── logo-96-96.png
│   ├── logo-512-512.png
│   ├── logo.png
│   ├── favicon.ico
│   └── redis
│
├── ...
├── vite.config.js

Vite

The first step is to create a vite project:

npm create vite@latest pwa -- --template vue

After that install firebase:

npm install --save firebase

Now let’s start by configuring vite.config.js to support PWA. I recommend using the following configurations:

vite.config.jsvite.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { VitePWA } from 'vite-plugin-pwa';

export default defineConfig({
  base: '',
  plugins: [
    vue(),
    VitePWA({
      mode: 'development',
      injectManifest: {
        globPatterns: ['**/*'],
      },
      strategies: 'injectManifest',
      srcDir: 'public',
      filename: 'firebase-messaging-sw.js',
      manifest: {
        name: 'D-RSS',
        short_name: 'D-RSS',
        theme_color: '#06091c',
        display: 'standalone',
        background_color: '#06091c',
        icons: [
          {
            src: 'logo-48-48.png',
            sizes: '48x48',
            type: 'image/png',
          },
          {
            src: 'logo-96-96.png',
            sizes: '96x96',
            type: 'image/png',
          },
          {
            src: 'logo-512-512.png',
            sizes: '512x512',
            type: 'image/png',
          },
          {
            src: 'logo-512-512.png',
            sizes: '512x512',
            type: 'image/png',
            purpose: 'any maskable',
          },
        ],
      },
    })
  ],
});

Important notes. By using strategies: injectManifest' we can build our own service worker, in this case to support firebase cloud messaging. To make this app fully cached and fully offline-available, we need to use the following parameter injectManifest:{globPatterns:['**/*']}*.

To build the service worker (firebase-messaging-sw.js) we first need to have at least this code:

import { precacheAndRoute } from 'workbox-precaching'
precacheAndRoute(self.__WB_MANIFEST)

To set up this app to receive all messages while the app is in the background, we will need the following configuration. Check this link to read more about firebase cloud-messaging.

firebase-messaging-sw.jsfirebase-messaging-sw.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import { precacheAndRoute } from 'workbox-precaching'

precacheAndRoute(self.__WB_MANIFEST)

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js');


// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
  apiKey: "AIzaSyCXPh_qT_9JTEbiUzFU57-fZZbDug63RiI",
  authDomain: "ddavidmelo-14dc2.firebaseapp.com",
  databaseURL: "https://ddavidmelo-14dc2.firebaseio.com",
  projectId: "ddavidmelo-14dc2",
  storageBucket: "ddavidmelo-14dc2.appspot.com",
  messagingSenderId: "211150998925",
  appId: "1:211150998925:web:2098c2ff8f71989ad141c4"
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
  console.log(
    '[firebase-messaging-sw.js] Received background message ',
    payload
  );
  // Customize notification here
  const notificationTitle = payload.notification.title;
  const notificationOptions = {
    body: payload.notification.body,
    icon: '/logo.png'
  };

  self.registration.showNotification(notificationTitle, notificationOptions);
});

To obtain the Firebase config object, you need to create a new web app in Firebase.

Now you are ready to build the project and serve it:

vite build
vite preview --host 0.0.0.0