Web Push ile ilgili bazı yaygın uygulama kalıplarına göz atacağız.
Bunun için, Service Worker'da bulunan farklı API'ler kullanılır.
Bildirim kapatma etkinliği
Son bölümde, notificationclick
etkinliklerini nasıl dinleyebileceğimizi ele aldık.
Ayrıca, kullanıcı bildirimlerinizden birini kapatırsa (örneğin, kullanıcı bildirimi tıklamak yerine, artı işaretini tıklar veya bildirimi hızlıca kaydırırsa) çağrılan bir notificationclose
etkinliği de vardır.
Bu etkinlik normalde kullanıcıların bildirimlerle etkileşimini izlemek amacıyla analizler için kullanılır.
self.addEventListener('notificationclose', function (event) {
const dismissedNotification = event.notification;
const promiseChain = notificationCloseAnalytics();
event.waitUntil(promiseChain);
});
Bildirime veri ekleme
Bir push mesajı alındığında, yaygın olarak yalnızca kullanıcı bildirimi tıkladıysa yararlı olan veriler bulunur. Örneğin, bir bildirim tıklandığında açılması gereken URL.
Bir push etkinliğindeki verileri almanın ve bunu bir bildirime eklemenin en kolay yolu, showNotification()
yöntemine geçirilen seçenekler nesnesine bir data
parametresi eklemektir. Örneğin:
const options = {
body:
'This notification has data attached to it that is printed ' +
"to the console when it's clicked.",
tag: 'data-notification',
data: {
time: new Date(Date.now()).toString(),
message: 'Hello, World!',
},
};
registration.showNotification('Notification with Data', options);
Tıklama işleyici içinde, verilere event.notification.data
ile erişilebilir.
const notificationData = event.notification.data;
console.log('');
console.log('The notification data has the following parameters:');
Object.keys(notificationData).forEach((key) => {
console.log(` ${key}: ${notificationData[key]}`);
});
console.log('');
Pencere açma
Bir bildirime verilen en yaygın yanıtlardan biri, belirli bir URL'ye yönlendiren bir pencere / sekme açmaktır. Bu işlemi clients.openWindow()
API ile yapabiliriz.
notificationclick
etkinliğimizde şunun gibi bir kod çalıştırırız:
const examplePage = '/demos/notification-examples/example-page.html';
const promiseChain = clients.openWindow(examplePage);
event.waitUntil(promiseChain);
Bir sonraki bölümde, kullanıcıyı yönlendirmek istediğimiz sayfanın zaten açık olup olmadığını nasıl kontrol edeceğimize bakacağız. Bu şekilde, yeni sekmeler açmak yerine açık sekmeye odaklanabiliriz.
Mevcut bir pencereye odaklanma
Mümkün olduğunda, kullanıcı bir bildirimi her tıkladığında yeni bir pencere açmak yerine bir pencereyi odaklamalıyız.
Bunu nasıl başarabileceğinize bakmadan önce, bunun yalnızca kaynağınızdaki sayfalar için mümkün olduğunu vurgulamakta fayda vardır. Çünkü yalnızca sitemize ait açık olan sayfaları görebiliyoruz. Bu, geliştiricilerin, kullanıcılarının görüntülediği tüm siteleri görmelerini engeller.
Önceki örnekten devam edersek, /demos/notification-examples/example-page.html
alanının zaten açık olup olmadığını görmek için kodu değiştireceğiz.
const urlToOpen = new URL(examplePage, self.location.origin).href;
const promiseChain = clients
.matchAll({
type: 'window',
includeUncontrolled: true,
})
.then((windowClients) => {
let matchingClient = null;
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
if (windowClient.url === urlToOpen) {
matchingClient = windowClient;
break;
}
}
if (matchingClient) {
return matchingClient.focus();
} else {
return clients.openWindow(urlToOpen);
}
});
event.waitUntil(promiseChain);
Şimdi, kodun üzerinden geçelim.
İlk olarak URL API'sını kullanarak örnek sayfamızı ayrıştırırız. Bu, Jeff Posnick'ten aldığım pratik bir numara. location
nesnesiyle new URL()
çağrıldığında, iletilen dize göreliyse (yani /
, https://example.com/
haline gelirse) mutlak URL döndürür.
Daha sonra pencere URL'leriyle eşleştirebilmek için URL'yi mutlak hale getiririz.
const urlToOpen = new URL(examplePage, self.location.origin).href;
Daha sonra, şu anda açık olan sekme ve pencerelerin listesi olan WindowClient
nesnelerinin bir listesini alırız. (Bunların yalnızca kaynağınıza ilişkin sekmeler olduğunu unutmayın.)
const promiseChain = clients.matchAll({
type: 'window',
includeUncontrolled: true,
});
matchAll
işlevine iletilen seçenekler, tarayıcıya yalnızca "pencere" türü istemcileri aramak (yani yalnızca sekmeleri ve pencereleri arayarak ve web çalışanlarını hariç tutmak) istediğimizi bildirir. includeUncontrolled
, kaynağınızda mevcut hizmet çalışanı (bu kodu çalıştıran hizmet çalışanı) tarafından kontrol edilmeyen tüm sekmeleri aramamızı sağlar. Genellikle, matchAll()
çağrısı yaparken includeUncontrolled
değerinin doğru olmasını istersiniz.
İade edilen sözü promiseChain
olarak yakalarız. Böylece daha sonra event.waitUntil()
hizmetine iletebilir ve hizmet çalışanlarımızı canlı tutabiliriz.
matchAll()
vaadi çözümlendiğinde, döndürülen pencere istemcilerini yineler ve URL'lerini, açmak istediğimiz URL ile karşılaştırırız. Eşleşme bulunursa o müşteriye odaklanırız
ve bu pencere kullanıcıların dikkatini çeker. matchingClient.focus()
çağrısıyla odaklama
tamamlanır.
Eşleşen bir müşteri bulamazsak, önceki bölümde olduğu gibi yeni bir pencere açarız.
.then((windowClients) => {
let matchingClient = null;
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
if (windowClient.url === urlToOpen) {
matchingClient = windowClient;
break;
}
}
if (matchingClient) {
return matchingClient.focus();
} else {
return clients.openWindow(urlToOpen);
}
});
Bildirimleri birleştirme
Bir bildirime etiket eklemenin, aynı etikete sahip mevcut bir bildirimin değiştirildiği bir davranışı etkinleştirdiğini gördük.
Bununla birlikte, Notifications API'yi kullanarak bildirimlerin daraltılması hakkında daha ayrıntılı bilgi edinebilirsiniz. Bir sohbet uygulamasını düşünün. Geliştiricinin, yalnızca en son mesajı göstermek yerine, "Met'ten iki mesajınız var" benzeri bir mesaj gösterecek yeni bir bildirim görmek isteyeceği bir uygulama düşünün.
Web uygulamanız için görünür durumdaki tüm bildirimlere erişmenizi sağlayan registration.getNotifications() API'sini kullanarak bunu yapabilir veya mevcut bildirimleri başka şekillerde değiştirebilirsiniz.
Chat örneğini uygulamak için bu API'yi nasıl kullanabileceğimize bakalım.
Sohbet uygulamamızda, her bildirimin kullanıcı adı içeren birtakım veriler içerdiğini varsayalım.
Yapmak istediğimiz ilk şey, belirli bir kullanıcı adına sahip bir kullanıcıya ait açık bildirimleri bulmaktır. registration.getNotifications()
kodunu alıp bunları döngüye alacağız ve notification.data
içinde belirli bir kullanıcı adı olup olmadığını kontrol edeceğiz:
const promiseChain = registration.getNotifications().then((notifications) => {
let currentNotification;
for (let i = 0; i < notifications.length; i++) {
if (notifications[i].data && notifications[i].data.userName === userName) {
currentNotification = notifications[i];
}
}
return currentNotification;
});
Bir sonraki adım, bu bildirimi yeni bir bildirimle değiştirmektir.
Bu sahte mesaj uygulamasında, yeni bildirim verilerimize bir sayı ekleyerek yeni mesaj sayısını izliyor ve her yeni bildirimle birlikte bu sayıyı artırıyoruz.
.then((currentNotification) => {
let notificationTitle;
const options = {
icon: userIcon,
}
if (currentNotification) {
// We have an open notification, let's do something with it.
const messageCount = currentNotification.data.newMessageCount + 1;
options.body = `You have ${messageCount} new messages from ${userName}.`;
options.data = {
userName: userName,
newMessageCount: messageCount
};
notificationTitle = `New Messages from ${userName}`;
// Remember to close the old notification.
currentNotification.close();
} else {
options.body = `"${userMessage}"`;
options.data = {
userName: userName,
newMessageCount: 1
};
notificationTitle = `New Message from ${userName}`;
}
return registration.showNotification(
notificationTitle,
options
);
});
Görüntülenmekte olan bir bildirim varsa mesaj sayısını artırırız ve bildirim başlığı ile gövde mesajını buna göre ayarlarız. Bildirim yoksa newMessageCount
/1 ile yeni bir bildirim oluştururuz.
Sonuç olarak ilk ileti aşağıdaki gibi görünür:
İkinci bir bildirim, bildirimleri şu şekilde daraltır:
Bu yaklaşımın iyi tarafı, kullanıcınızın bildirimlerin birbiri üzerine göründüğüne şahit olması durumunda bildirimi en son mesajla değiştirmekten daha tutarlı görünmesidir.
Kural istisnası
Push aldığınızda bildirim göstermeniz gerektiğini belirtmiştim. Bu durum, çoğu zaman doğrudur. Bildirim göstermek zorunda kalmayacağınız tek senaryo, kullanıcının sitenizi açık ve odaklanmış olduğu zamandır.
Push etkinliğinizde, pencere istemcilerini inceleyerek ve odaklanılmış bir pencere arayarak bildirim göstermeniz gerekip gerekmediğini kontrol edebilirsiniz.
Tüm pencereleri almak ve odaklanmış bir pencere aramak için gereken kod şuna benzer:
function isClientFocused() {
return clients
.matchAll({
type: 'window',
includeUncontrolled: true,
})
.then((windowClients) => {
let clientIsFocused = false;
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
if (windowClient.focused) {
clientIsFocused = true;
break;
}
}
return clientIsFocused;
});
}
Tüm pencere istemcilerimizi almak için clients.matchAll()
kullanıyoruz ve ardından focused
parametresini kontrol edip bunların üzerinden geçiyoruz.
Push etkinliğimizde bir bildirim göstermemize karar vermek için şu işlevi kullanırız:
const promiseChain = isClientFocused().then((clientIsFocused) => {
if (clientIsFocused) {
console.log("Don't need to show a notification.");
return;
}
// Client isn't focused, we need to show a notification.
return self.registration.showNotification('Had to show a notification.');
});
event.waitUntil(promiseChain);
Push etkinliğinden bir sayfaya mesaj gönderme
Kullanıcı o sırada sitenizde bulunuyorsa bildirim göstermeyi atlayabileceğinizi fark ettik. Ancak, kullanıcıya bir etkinliğin gerçekleştiğini ancak bildirimin elle çok ağır davrandığını yine de bildirmek istiyorsanız ne olur?
Bu yaklaşımlardan biri, Service Worker'dan sayfaya mesaj göndermektir. Bu sayede web sayfası, kullanıcıya etkinlik hakkında bilgi veren bir bildirim veya güncelleme gösterebilir. Bu, sayfadaki küçük bir bildirimin kullanıcı için daha iyi ve daha dostça olduğu durumlarda faydalıdır.
Bir bildirim aldığımızı, web uygulamamızın şu anda odaklandığını kontrol ettiğimizi ve ardından her açık sayfaya aşağıdaki şekilde bir "mesaj yayınlayabileceğimizi" varsayalım:
const promiseChain = isClientFocused().then((clientIsFocused) => {
if (clientIsFocused) {
windowClients.forEach((windowClient) => {
windowClient.postMessage({
message: 'Received a push message.',
time: new Date().toString(),
});
});
} else {
return self.registration.showNotification('No focused windows', {
body: 'Had to show a notification instead of messaging each page.',
});
}
});
event.waitUntil(promiseChain);
Sayfaların her birinde, bir mesaj etkinliği işleyici ekleyerek mesajları dinleriz:
navigator.serviceWorker.addEventListener('message', function (event) {
console.log('Received a message from service worker: ', event.data);
});
Bu mesaj işleyicide, istediğiniz her şeyi yapabilir, sayfanızda özel bir kullanıcı arayüzü gösterebilir veya mesajı tamamen yoksayabilirsiniz.
Ayrıca web sayfanızda bir mesaj işleyici tanımlamazsanız Service Worker'dan gelen mesajların hiçbir şey yapmayacağını unutmayın.
Bir sayfayı önbelleğe alma ve bir pencere açma
Bu kılavuzun kapsamı dışında kalan ancak tartışmaya değer bir senaryo, kullanıcıların bildiriminizi tıkladıktan sonra ziyaret etmelerini beklediğiniz web sayfalarını önbelleğe alarak web uygulamanızın genel kullanıcı deneyimini iyileştirebileceğinizdir.
Bunun için hizmet çalışanınızın fetch
etkinliklerini işleyecek şekilde ayarlanması gerekir ancak bir fetch
etkinlik işleyici uygularsanız bildirimi göstermeden önce sayfayı ve ihtiyacınız olacak öğeleri önbelleğe alarak push
etkinliğinizde bundan yararlandığınızdan emin olun.
Tarayıcı uyumluluğu
notificationclose
etkinliği
Clients.openWindow()
ServiceWorkerRegistration.getNotifications()
clients.matchAll()
Daha fazla bilgi için Service Worker'lara giriş konulu bu yayına göz atın.
Sonraki adımlar
- Web Push Bildirimine Genel Bakış
- Push'un İşleyişi
- Kullanıcıya Abone Olma
- İzin Kullanıcı Deneyimi
- Web Push Kitaplıklarıyla Mesaj Gönderme
- Web Push Protokolü
- Push Etkinliklerini Yönetme
- Bildirim Görüntüleme
- Bildirim Davranışı
- Sık Karşılaşılan Bildirim Kalıpları
- Push Bildirimleriyle İlgili SSS
- Sık Karşılaşılan Sorunlar ve Hata Bildirme