avatar

麦兜的小站

MDO.INK

  • 首页
  • 随笔
  • 知识库
  • 归档
  • 动态
  • 标签
  • 关于
Home Notification in Browsers
文章

Notification in Browsers

Posted 2025-02-11 Updated 2025-02- 11
By power 已删除用户
24~32 min read

How nice would it be to have notifications in browsers like a regular mobile application?

Well, we already have it!

There are just a couple of concepts we need to master before start:

  1. Browser support
  2. Notifications permissions
  3. Service Workers

Does the browser support it?

First of all, we need to check if the browser supports the Notification and the serviceworker features. Without these services we cannot manage notifications!

It is as easy as typing:

if (!('serviceWorker' in navigator)) {
  throw new Error('No Service Worker support')
}
if (!("Notification" in window)) {
  throw new Error('No Notification support')
}

NB: This applies to any browser feature.

Notifications permissions

In order to activate notifications on a specific device, the user must be asked if they want to receive notifications.

Notification.requestPermission()

An alert will pop up in the browser asking the user to respond…

…and our application must handle the user's choice in this way:

Notification.requestPermission().then((permission) => {
  if (permission === "granted") {
    // The user clicked on "Allow" button
    // Browser CAN send notifications
  } else if (permission === "denied") {
    // The user clicked on "Block" button
    // Browser CANNOT send notifications
  } else if (permission === "default") {
    // The user closed the popup
    // we can ask for permissions again if we want!
  }
});

Okay, now we may be ready to send our first notification to the user, but first let's talk about ServiceWorker!

ServiceWorker

According to MDN Service Workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available).

Practically speaking, a ServiceWorker is a JavaScript file that runs in the background in a separate thread. It must be registered (installed) first, and then it can talk with the application (NB: https is mandatory!)

Why do we need a ServiceWorker to send notification? Because it runs in the background even if our application page is not open in the browser! And, above all, because the SerciveWorkerRegistration has a method called showNotification which is used to displays the notification on the device.

Send a notification

We just have to wait until the service worker is ready and call the method by passing the notification title as the first parameter.

navigator.serviceWorker.ready.then((swRegistration) => {
  swRegistration.showNotification("My First notification!");
})

These few lines of code will show the notification:

Notification properties

The showNotification method has a second argument that accepts an object of options which allows us to customize the notification:

  • icon: an URL representing an image that will be displayed next to the notification title
  • image: an URL representing an image that will be displayed as a content of the notification
  • actions: an array of actions that will result in a list of clickable buttons below the notification content
  • action: a unique string representing the ID of the action
  • title: a human readable string to be displayed
  • icon: an URL representing the image next to the title
  • body: A string representing an extra content to display within the notification.
  • badge: a string containing the URL of an image to represent the notification when there is not enough space to display the notification itself such as for example, the Android Notification Bar.
  • data: Arbitrary data that you want to be associated with the notification
  • tag: An ID for a given notification that allows you to find, replace, or remove the notification using a script if necessary.
  • silent: if true, no vibration or alert sound
  • vibrate: an array of numbers representing the vibration patter
  • …and many more!

"Come back" notification

Let's try creating together a "come back" notification that shows up when the application lose focus and hides automatically when it is on focus again. It also takes the user directly back to the application if the notification is clicked.

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.serviceWorker.ready.then(async registration => {
      await registration.showNotification("Come baaaaack!", {
        body: `Click here and come back to the website!`,
        silent: true,
        tag: "come-back", // required if silent is set to "true"
      });
      registration.addEventListener('click', (e) => {
        e.preventDefault();
        window.parent.focus();
      });
    });
  } else {
    navigator.serviceWorker.ready.then(registration => {
      registration.getNotifications({
        tag: 'come-back'
      }).then((notifications) => {
        notifications.forEach(n => {
          n.close();
        })
      });
    })
  }
});

Notifications without ServiceWorker

"What?! You just said that ServiewWorker are required to send notification!!" I know… There is an alternative method which doesn't involve ServiceWorker actually, but it relies on a deprecated feature! The window.Notification constructor is not marked as deprecated, however, it’s marked as deprecated in Chrome on Android, thus it won't work on mobile devices! This is why I preferred to use the ServiceWorker method directly!

I'm going to write an example because it might be interesting for those who don't deal with mobile browsers!

"OLD" way: Notification constructor

Let's re-create the "come back" notification using the Notification constructor.

let comeBackNotification;
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    comeBackNotification = new Notification("Come baaaaack!");

    comeBackNotification.addEventListener('close', (e) => {
      console.log("Notification CLOSED!", e.target.data)
    });

    comeBackNotification.addEventListener('click', (e) => {
      console.log("Notification CLICKED!", e.target.data)
      e.preventDefault();
      window.parent.focus();
    });
  } else {
    comeBackNotification.close();
  }
})

Good to know

  • Starting in Chrome 49, notifications don't work in incognito mode.
  • notification.vibrate doesn't work in Android > 8.0
  • sw.js, if we don't need it, it could be just an empty file!
  • Chrome for Android requires the call to be made with a service worker registration
  • iOS requires website to first be added to the Home Screen

Wait Until

One of the things to understand about service workers is that you have little control over when the service worker code is going to run. The browser decides when to wake it up and when to terminate it. The only way you can tell the browser to wait, is to pass a promise into the event.waitUntil() method. With this, the browser will keep the service worker running until the promise you passed in has settled.

// file: `sw,js`
self.addEventListener('push', function(event) {
  const promiseChain = self.registration.showNotification("Push Notification");
  event.waitUntil(promiseChain);
})

Push Notifications (from remote server)

The essential difference between local notifications and push notifications is simple:

  • Local notifications are scheduled by an app locally and are delivered by the same device.

  • Push notifications are sent by a remote server which sends these notifications to devices on which the app is installed.

I won't talk about the server side part, thus I'm going to explain how to simulate a Push Notification using Chrome DevTools.

Simulate a Push Notification with Chrome DevTools:

  • Open Chrome DevTools
  • Go to Application tab
  • Select Service Workers on the left
  • Write a custom message on the right anche click Push

Demo

As usual, I created a demo and a GitHub project

While running the demo, check the console for more information.

知识库
License:  CC BY 4.0
Share

Further Reading

Jul 31, 2025

如何实现接口幂等性

通俗的说,用户在系统中有操作,不管重复多少次,都应该产生一样的效果或返回一样的结果的。 幂等性的概念 幂等(Idempotent)是一个数学与计算机学的概念,常见于抽象代数中。 f(n)=1^n//无...

Jul 19, 2025

10个npm工具包

有了npm之后,前端人员真的是过上好日子了。我们可以直接把别人写好的工具包拿来用,非常的方便。 1.day.js-轻量日期处理 npminstalldayjs importdayjsfrom'd...

Jul 17, 2025

How to set up PHP7.4 on MacOS.

Thisisallverywellandgood.Apartfromonesmallinsignificantthing… TheversionofPHPinuseiscurrently7.4. Th...

OLDER

vue3中当路由一样,参数quary不一样的跳转

NEWER

针对Vue相同路由不同参数的不刷新问题的解决方案

Recently Updated

  • 如何实现接口幂等性
  • 10个npm工具包
  • How to set up PHP7.4 on MacOS.
  • Automa:一键自动化,网页数据采集与工作流程优化专家Automa:解锁自动化
  • Mac 下用 brew 搭建 LNMP

Trending Tags

thinkphp clippings

Contents

©2025 麦兜的小站. Some rights reserved.

Using the Halo theme Chirpy