[ReactJS] Push notification sử dụng Firebase Cloud Messaging

Xin chào, trong bài viết này mình sẽ thực hiện chức năng push notification trên trang web ReactJS sử dụng Firebase Cloud Messaging (FCM) Các bước chính Khởi tạo project ReactJS Tạo project Firebase và setup FCM Cấu hình Firebase trong app ReactJS để nhận message push từ FCM a. Foreground b. Background 1. Khởi

Xin chào, trong bài viết này mình sẽ thực hiện chức năng push notification trên trang web ReactJS sử dụng Firebase Cloud Messaging (FCM)

Các bước chính

  1. Khởi tạo project ReactJS
  2. Tạo project Firebase và setup FCM
  3. Cấu hình Firebase trong app ReactJS để nhận message push từ FCM
    a. Foreground
    b. Background

1. Khởi tạo project ReactJS

Để khởi tạo project ReactJS đơn giản, mình sử dụng create-react-app:

npx create-react-app demo-fcm --template typescript

Sau đó chạy thử project:

cd demo-fcm
npm start

Kết quả:
image.png

2. Tạo project Firebase và setup FCM

Đăng nhập vào Firebase Console, chọn Add project:
Screen Shot 2022-08-25 at 14.35.01.png
Mình đặt tên là demo-fcm, chọn ContinueCreate project
Screen Shot 2022-08-25 at 14.35.45.png
Đợt 1 chút để project được khởi tạo xong, chọn Continue.
Tại trang chủ của project, bấm vào biểu tượng < /> để setup cho Web
Screen Shot 2022-08-25 at 14.38.45.png
Mình đặt tên là demo-fcm-app, chọn** Register app**
Screen Shot 2022-08-25 at 14.40.50.png
Chọn Continue to console
Tại màn hình chính của project, ở menu bên trái, nhấn vào biểu tượng răng cưa, chọn Project settings. Sau đó chọn tab Cloud Messaging
Screen Shot 2022-08-25 at 14.46.16.png
Ở phần Cloud Messaging API (Legacy) (đang hiện Disable), chọn biểu tượng 3 chấm => Manage API in Google Cloud Console
Ở cửa sổ mở ra, chọn Enable:
Screen Shot 2022-08-25 at 14.47.53.png
Sau đó reload lại trang Project settings, phần Cloud Messaging API (Legacy) đã được Enabled và bên dưới là Server key
Tại phần Web Push certificates, bấm vào Generate key pair: (cái này là VAPID key)
Screen Shot 2022-08-25 at 16.42.08.png
Như vậy là đã cấu hình setup xong project Firebase

3. Cấu hình Firebase trong app ReactJS để nhận message push từ FCM

Trước tiên mình sẽ install package firebase, ở đây mình dùng firebase version 8:

npm install [email protected]

Tạo file constants.ts trong thư mục src để lưu Firebase config:

//src/constants.ts
export const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: "your_auth_domain",
  projectId: "your_projectId",
  storageBucket: "your_storage_bucket",
  messagingSenderId: "your_messaging_sender_id",
  appId: process.env.REACT_APP_FIREBASE_APP_ID
};

Config lấy từ Project settings, tab General:
Screen Shot 2022-08-25 at 17.15.53.png

a. Foreground

Để nhận foreground message (khi đang ở tab trang web), mình sẽ viết 1 hàm lắng nghe message khi đang focus vào web.
Trong thư mục src, tạo file firebase.ts với nội dung:

import { useEffect } from 'react';
import firebase from "firebase/app";
import "firebase/messaging";
import { firebaseConfig } from './constants';

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
} else {
  firebase.app(); // if already initialized, use that one
}

let messaging: firebase.messaging.Messaging;

if (typeof window !== "undefined") {
  if (firebase.messaging.isSupported()) {
    messaging = firebase.messaging();
  }
}

export const getMessagingToken = async () => {
  let currentToken = "";
  if (!messaging) return;
  try {
    currentToken = await messaging.getToken({
      vapidKey: process.env.REACT_APP_FIREBASE_FCM_VAPID_KEY,
    });
    console.log("FCM registration token", currentToken);
  } catch (error) {
    console.log("An error occurred while retrieving token. ", error);
  }
  return currentToken;
};

export const onMessageListener = () =>
  new Promise((resolve) => {
    messaging.onMessage((payload) => {
      resolve(payload);
    });
  });

File này mình định nghĩa hàm onMessageListener để hứng message, hàm này có thể được gọi trong useEffect:
Trong file App.tsx, mình thêm 2 useEffect sau:

useEffect(() => {
    getMessagingToken();
  },[])
 useEffect(() => {
   onMessageListener().then(data => {
      console.log("Receive foreground: ",data)
   })
})

useEffect đầu tiên dùng để lấy Registration token từ Firebase
useEffect sau dùng để hứng message được push từ Firebase (lưu ý là useEffect này không có dependencies)
Chạy thử project lên xem nhé:
Trang web sẽ yêu cầu cho phép gửi thông báo, chọn Cho phép, ta sẽ thấy FCM registration token được console.log ra:
Screen Shot 2022-08-25 at 17.42.47.png
Thử bắn message từ firebase (lưu ý là phải đang mở tab của trang web):
Vào Firebase, tại menu bên trái, chọn Engage => Cloud Messaging => Send your first message:
Screen Shot 2022-08-25 at 17.45.21.png
Chọn Send test message, paste token được console.log ra ở trên và chọn +
Screen Shot 2022-08-25 at 17.46.00.png
Chọn Test và message được bắn về trang web:
Screen Shot 2022-08-25 at 17.47.37.png
Như vậy là chức năng push notification foreground đã hoạt động.

b. Background

Để push notification từ background, cần phải có service workers
Ở thư mục gốc, tạo file firebase-messaging-sw.js với nội dung sau:

//src/firebase-messaging-sw.js
import {firebaseConfig} from './src/firebase'
if ('serviceWorker' in navigator) {
  const firebaseConfigParams = new URLSearchParams(firebaseConfig).toString();
  navigator.serviceWorker
    .register(`../firebase-messaging-sw.js?${firebaseConfigParams}`)
    .then(function (registration) {
      console.log('Registration successful, scope is:', registration.scope);
    })
    .catch(function (err) {
      console.log('Service worker registration failed, error:', err);
    });
}

Ở file này mình sẽ register 1 service worker với params là firebaseConfig được import từ constants mà mình trình bày ở phần a.
Trong thư mục public, mình tạo 1 file firebase-messaging-sw.js với nội dung sau:

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

self.addEventListener('fetch', () => {
  const urlParams = new URLSearchParams(location.search);
  self.firebaseConfig = Object.fromEntries(urlParams);
});

const defaultConfig = {
  apiKey: true,
  projectId: true,
  messagingSenderId: true,
  appId: true,
};

firebase.initializeApp(self.firebaseConfig || defaultConfig);
if (firebase.messaging.isSupported()) {
  const messaging = firebase.messaging();
  const channel = new BroadcastChannel('notifications');
  messaging.onBackgroundMessage(function (payload) {
    //can not console.log here
    channel.postMessage(payload);
  });
}

Đây chính là file service worker. File này sẽ initilize Firebase app và hứng message từ background.
Sau khi nhận được background message, mình sẽ muốn console.log ra để xem. Tuy nhiên do luồng service worker chạy độc lập nên sẽ không thể console.log ở trong file này.
Mình sẽ dùng BroadcastChannel để giao tiếp giữa luồng service worker và luồng web:

...
const channel = new BroadcastChannel('notifications');
...
channel.postMessage(payload);

Tiếp theo là ở luồn web, mình nhận data từ BroadcastChannel và console.log ra thôi.
Tại file App.tsx, mình thêm đoạn code vào useEffect đầu tiên, sau khi thêm thì nó sẽ như thế này:

//src/App.tsx
...
useEffect(() => {
    getMessagingToken();
    const channel = new BroadcastChannel("notifications");
    channel.addEventListener("message", (event) => {
      console.log("Receive background: ", event.data);
    });
  },[])
...

Như vậy là trang web đã sẵn sàng nhận background message. Cùng thử xem nhé!
Ở trình duyệt, mình mở sang tab khác, sau đó test push message như ở phần a, và đây là kết quả khi mình quay lại tab trang Web:
Screen Shot 2022-08-26 at 11.23.18.png

Vừa rồi mình đã trình bày chức năng push notification sử dụng Firebase Cloud Messaging. Cảm ơn mọi người đã đọc bài viết!

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ