Implementace oznámení push s aplikací Firebase pro Javascript

Tato upozornění, na která jsme zvyklí na chytrých telefonech, jsou dostupná i v prostředí prohlížeče. Pokud víte, proč přesně jste zde, přeskočte tuto část a přejděte přímo k řešení.

A tato oznámení na webu nenávidíme, protože každý spamový web nás žádá o povolení k zasílání spamu. Užitečná je však samotná technologie. Webová oznámení push jsem dříve neimplementoval. Žádný takový případ nebyl, ale nedávno jsem potřeboval co nejdříve upozornit své uživatele na důležité informace. E-mail je dobrý, ale uživatel by si měl nejprve otevřít e-mailového klienta. S upozorněními se vyskakovací okno zobrazí okamžitě.

Rozhodl jsem se napsat tento článek, protože jsem nenašel komplexní informace o implementaci upozornění prohlížeče pro aplikace React, Next.JS, Node. K tomuto účelu budeme používat Firebase, abychom sami ušetřili čas tím, že nebudeme vytvářet řešení od začátku.

Přehled push notifikací prohlížeče

Takže jak jsme řekli, je to jako ta mobilní oznámení, ale používá se v prohlížečích většinou pro spamování. Stojí za zmínku, že je musíte odeslat uživateli, pokud je to skutečně to, k čemu se přihlásil. Příklady:

  • nové komentáře pod příspěvkem uživatele;
  • nová zpráva na nějaké platformě;
  • důležité informace, které by měly být zpracovány rychle;

Ostatní nedůležité věci mohou chodit na e-mail.

Jak to funguje

Nejprve požádáte uživatele o povolení zobrazovat oznámení. Pokud obdržíte souhlas, váš web nainstaluje servisního pracovníka, který bude zpracovávat oznámení. Odešlete také požadavek na registraci tohoto konkrétního uživatele na serveru pro zasílání zpráv, požádáte jej, aby někomu poslal upozornění.

Když server pro zasílání zpráv zaregistruje vaše uživatele, pošle vám jedinečný token vašeho uživatelského tokenu, který budete používat jako adresát k programovému odesílání oznámení push.

Registrační token uložíte ze serveru pro zasílání zpráv. Když chcete odeslat oznámení, upozorníte na tento token uživatele, kterému chcete poslat zprávu, takže server pro zasílání zpráv bude vědět, komu má oznámení poslat. Když uživatel souhlasí s přijímáním oznámení, váš web nainstaluje servisního pracovníka, je to skript na pozadí, který bude spuštěn v prohlížeči uživatele. Je naprogramován tak, aby zpracovával zprávy ze serveru pro zasílání zpráv. Když nějaké obdrží, sestaví oznámení, které se zobrazí tomuto uživateli.

Server pro zasílání zpráv? Toto je jakýkoli server, který ví, jak komunikovat s vaším servisním pracovníkem. Můžete si ho sestavit sami a naprogramovat servisního pracovníka, který odtud bude spravovat zprávy. Ale nebudeme si komplikovat život a budeme používat Firebase.

Oznámení Push Firebase

Pokud používáme Firebase, nestaráme se o správné nastavení serveru pro zasílání zpráv, protože jsme pokryti. Potřebujeme naprogramovat logiku, abychom mohli požádat o oprávnění k oznámení, nainstalovat servisního pracovníka a napsat logiku pro odesílání oznámení z naší aplikace.

Pro další nastavení byste měli vytvořit projekt ve Firebase Console a odtud mít konfiguraci (soubor JSON).

Nastavení rozhraní

Mám aplikaci Next.js, ale tento algoritmus pokrývá jakoukoli aplikaci napsanou v Javascriptu, je nezávislá na knihovně a frameworku.

Nainstalujte do svého projektu Firebase, abychom mohli využívat jednoduché funkce namísto ručního zadávání požadavků na FCM (Firebase Cloud Messaging).

$ npm install firebase
# or
$ yarn add firebase

Najděte místo, kde se chcete uživatele zeptat na povolení oznámení. Může to být například tlačítko, které říká „Přihlásit se k odběru upozornění prohlížeče“. Kliknutím na toto tlačítko zavoláte funkci getFCMToken() napsáno níže:

import { initializeApp } from 'firebase/app';
import { getMessaging, getToken } from 'firebase/messaging';

// Replace these values with your project's ones
// (you can find such code in the Console)
const firebaseConfig = {
    apiKey: 'xxxxx-xxx',
    authDomain: 'xxxx.firebaseapp.com',
    projectId: 'xxxx-xxxx',
    storageBucket: 'xxxx.appspot.com',
    messagingSenderId: '00000000',
    appId: '0:00000:00000000'
};

export const app = initializeApp(firebaseConfig);
const messaging = getMessaging();

export async function getFCMToken() {
    try {
        // Don't forget to paste your VAPID key here
        // (you can find it in the Console too)
        const token = await getToken(messaging, { vapidKey: <YOUR_VAPID_KEY> });
        return token;
    } catch (e) {
        console.log('getFCMToken error', e);
        return undefined
    }
}

Pomocí tohoto kódu inicializujeme knihovnu Firebase a napíšeme tento getFCMToken() funkce. Načte registrační token z FCM a také požádá uživatele o povolení oznámení . Pokud jsou oprávnění přijata, teprve poté bude komunikovat s FCM a zaregistrovat tohoto uživatele. Jinak kód vyvolá chybu, kterou zachytíte v catch blokovat.

Poté získáte token FCM (jedinečný token uživatele v systému FCM), který budete používat k odesílání oznámení. Musíte jej tedy uložit někde. Obvykle máte server, kam můžete poslat token a ten jej uloží do databáze pro tohoto konkrétního uživatele. V opačném případě nebudete moci uživatelům posílat upozornění. Je vyžadována sada Firebase Admin SDK, která je dostupná v serverových prostředích.

Existují však určité výjimky. V některých případech, kdy chcete uživatele pouze přihlásit k odběru oznámení, jako je tomu v bulletinu, nemusíte tokeny FCM ukládat. Firebase je má a oznámení můžete odesílat ručně z konzoly. Ale není možné je odesílat automaticky (programově), protože nemůžete rozlišit uživatele (nemáte tokeny).

A poslední věcí je mít servisního pracovníka, který bude vyřizovat notifikace z FCM. Vytvořte soubor, který bude dostupný v kořenovém adresáři vaší webové aplikace, soubor s názvem firebase-messaging-sw.js . Měl by být přístupný na https://yourwebsite.com/firebase-messaging-sw.js . Jeho obsah:

// It's a static script file, so it won't be covered by a module bundling system
// hence, it uses "importScripts" function to load the other libs
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js');

// Replace the values with yours
const firebaseConfig = {
    apiKey: 'xxx',
    authDomain: 'xxx',
    projectId: 'xxx',
    storageBucket: 'xxx',
    messagingSenderId: 'xxx',
    appId: 'xxx'
};

firebase.initializeApp(firebaseConfig);

const messaging = firebase.messaging();

// Not necessary, but if you want to handle clicks on notifications
self.addEventListener('notificationclick', (event) => {
    event.notification.close()

    const pathname = event.notification?.data?.FCM_MSG?.notification?.data?.link
    if (!pathname) return
    const url = new URL(pathname, self.location.origin).href

    event.waitUntil(
        self.clients
            .matchAll({ type: 'window', includeUncontrolled: true })
            .then((clientsArr) => {
                const hadWindowToFocus = clientsArr.some((windowClient) =>
                    windowClient.url === url ? (windowClient.focus(), true) : false
                )

                if (!hadWindowToFocus)
                    self.clients
                        .openWindow(url)
                        .then((windowClient) =>
                            windowClient ? windowClient.focus() : null
                        )
            })
    )
})

To je vše na přední straně! Tlačítko můžete otestovat, při tisku by vás mělo požádat o povolení (přesněji požádá prohlížeč), aby vám zasílal upozornění. Když to povolíte, měli byste vidět token FCM (console.zalogujte to někde)

Odesílání upozornění ze serveru

V mém případě je to server Node.js a budeme pro něj instalovat SDK, ale obecný princip je stejný pro ostatní jazyky/platformy.

$ npm install firebase-admin

V konzole máte také konfiguraci pro backend. Liší se od klienta na straně klienta, protože má soukromý klíč, který potřebujete k podepsání oznámení, které bude odesláno do FCM. Vložte toto firebase.json soubor (nazývá se to servisní účet) někde, aby byl přístupný z kódu, můžete jej vložit jako proměnnou prostředí.

Poté byste měli inicializovat knihovnu Firebase při spuštění serveru (nebo později, pokud chcete řídit tok). Tuto logiku jsem vložil do samostatného souboru:

import admin from 'firebase-admin';

import serviceAccount from './config/firebase.json';

export function init() {
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
    });
}

Při spuštění serveru zavolejte init() a Firebase je připravena vám sloužit.

Nebudu se zabývat ukládáním tokenů FCM, jsem si jistý, že víte, jak na to, a není to účelem tohoto článku. Pokud tedy máte na serveru inicializovanou Firebase (z posledního odstavce) a máte token FCM uživatele, jste připraveni odesílat oznámení push do prohlížeče uživatele! Vypadá to takto:

import { getMessaging } from 'firebase-admin/messaging';

// I use Typescript, you may not, but types will help you
// to understand what data structures FCM expects.
// It's an internal structure though, firebase-admin has
// good typings in the library
interface Message {
    title: string;
    body: string;
    requireInteraction?: boolean;
    link?: string;
}

// Use this function to send push notifications to a specific user
export async function sendFCMMessage(fcmToken: string, msg: Message): Promise<string> {
    try {
        const res = await getMessaging().send({
            webpush: {
                notification: {
                    ...msg,
                    icon: 'https://your-website.com/favicon.png',
                    requireInteraction: msg.requireInteraction ?? false,
                    actions: [{
                        title: 'Open',
                        action: 'open',
                    }],
                    data: {
                        link: msg.link,
                    },
                },
            },
            token: fcmToken,
        });
        return res;
    } catch (e) {
        console.error('sendFCMMessage error', e);
    }
}

Nyní několik podrobností o užitečné zátěži oznámení. Firebase podporuje různé platformy, zde používám webpush pole pro mé užitečné zatížení. FCM podporuje další pole:

interface BaseMessage {
    data?: {
        [key: string]: string;
    };
    notification?: Notification;
    android?: AndroidConfig;
    webpush?: WebpushConfig;
    apns?: ApnsConfig;
    fcmOptions?: FcmOptions;
}

Zkusil jsem použít notification jako univerzální, ale měl jsem problémy s klikáním na oznámení, prohlížeč nezpracovával kliknutí (servisní pracovník měl obslužný program kliknutí). Navíc byly problémy se zobrazováním ikon v oznámeních. Je lepší použít webpush pokud cílíte na uživatele stolních počítačů. Token FCM může být pro různé platformy:Android, iOS, web.

Uvnitř webpush , je jich title a body které odpovídají názvu a textu oznámení. Je tam icon pokud chcete, aby vaše oznámení mělo ikonu. Vložte veřejně přístupný obrázek, který chcete zobrazit. Nastavte requireInteraction na true Pokud nechcete, aby se oznámení po několika sekundách zavřelo, mělo by počkat na výslovnou reakci uživatele.

Existuje vlastní link pole uvnitř data , je zaměřena na to, aby servisní pracovník byl přečten a správně zpracoval kliknutí na oznámení.

Nevím o všech prohlížečích, ale můj prohlížeč (Brave) nezvládá výchozí upozornění na kliknutí na celou oblast, měla by tam být vlastní tlačítka. Definuji je v actions pole. Zdá se, že nezáleží na tom, jaká tlačítka s akcemi vložím, tlačítko „Otevřít“ (akce) otevře adresu URL z data.link vlastnost, kterou posílám.

Souhrn

Webová oznámení push není obtížné implementovat, pokud můžete používat Firebase. Je také snadné odesílat zprávy na různá zařízení na různých platformách. Získejte pouze token FCM na straně klienta (na mobilu, webu nebo počítači) a posílejte oznámení ze serveru.

Zdroj