Langkah pertama adalah mendapatkan izin dari pengguna
untuk mengirim pesan {i>push<i} kepada mereka dan kemudian kita bisa
mendapatkan PushSubscription
.
JavaScript API untuk melakukan hal ini cukup mudah, jadi mari kita lanjutkan melalui aliran logika.
Deteksi fitur
Pertama, kita perlu memeriksa apakah browser saat ini benar-benar mendukung pengiriman pesan push. Kita dapat memeriksa apakah push didukung dengan dua pemeriksaan sederhana.
- Periksa serviceWorker pada navigator.
- Periksa PushManager di window.
if (!('serviceWorker' in navigator)) {
// Service Worker isn't supported on this browser, disable or hide UI.
return;
}
if (!('PushManager' in window)) {
// Push isn't supported on this browser, disable or hide UI.
return;
}
Sementara dukungan browser berkembang dengan cepat untuk pekerja layanan dan pengiriman pesan push, ada baiknya untuk melakukan deteksi fitur untuk secara progresif meningkat.
Mendaftarkan pekerja layanan
Dengan deteksi fitur, kita tahu bahwa pekerja layanan dan Push didukung. Langkah selanjutnya adalah dengan "mendaftar" pekerja layanan kita.
Ketika mendaftarkan pekerja layanan, kita memberi tahu browser letak file pekerja layanan kita. File masih berupa JavaScript, tetapi browser akan "memberikan akses" ke pekerja layanan API, termasuk push. Lebih tepatnya, browser menjalankan file di pekerja layanan lingkungan fleksibel App Engine.
Untuk mendaftarkan pekerja layanan, panggil navigator.serviceWorker.register()
, dengan meneruskan jalur ke
file kita. Seperti ini:
function registerServiceWorker() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
console.log('Service worker successfully registered.');
return registration;
})
.catch(function (err) {
console.error('Unable to register service worker.', err);
});
}
Fungsi ini memberi tahu browser bahwa kita memiliki file pekerja layanan dan lokasinya. Di beberapa
dalam hal ini, file pekerja layanan berada di /service-worker.js
. Di balik layar browser
akan melakukan langkah-langkah berikut setelah memanggil register()
:
Download file pekerja layanan.
Jalankan JavaScript.
Jika semuanya berjalan dengan benar dan tidak ada error, promise yang ditampilkan oleh
register()
akan teratasi. Jika ada error apa pun, promise akan ditolak.
Jika
register()
menolak, periksa kembali JavaScript Anda untuk menemukan kesalahan ketik / error di Chrome DevTools.
Saat register()
di-resolve, metode ini akan menampilkan ServiceWorkerRegistration
. Kita akan menggunakan
pendaftaran Anda untuk mengakses PushManager API.
Kompatibilitas browser PushManager API
Meminta izin
Kita telah mendaftarkan pekerja layanan kita dan siap membuat pengguna berlangganan, langkah selanjutnya adalah mendapatkan izin akses dari pengguna untuk mengirim pesan {i>push<i} kepada mereka.
API untuk mendapatkan izin relatif sederhana, kekurangannya adalah API baru-baru ini berubah dari mengambil callback menjadi menampilkan Promise. Tujuan masalah ini, yaitu kita tidak bisa mengetahui versi API mana yang diimplementasikan oleh sehingga Anda harus menerapkan keduanya dan menangani keduanya.
function askPermission() {
return new Promise(function (resolve, reject) {
const permissionResult = Notification.requestPermission(function (result) {
resolve(result);
});
if (permissionResult) {
permissionResult.then(resolve, reject);
}
}).then(function (permissionResult) {
if (permissionResult !== 'granted') {
throw new Error("We weren't granted permission.");
}
});
}
Dalam kode di atas, cuplikan kode yang penting adalah panggilan ke
Notification.requestPermission()
. Metode ini akan menampilkan perintah kepada pengguna:
Setelah pengguna berinteraksi dengan dialog izin
dengan menekan {i>Allow<i}, Blokir, atau hanya menutupnya,
kita akan diberi hasilnya sebagai string: 'granted'
, 'default'
, atau 'denied'
.
Pada kode contoh di atas, promise yang ditampilkan oleh askPermission()
akan di-resolve jika izin
diberikan, jika tidak, kita akan menampilkan error yang membuat promise ditolak.
Satu kasus ekstrem yang perlu Anda tangani adalah jika pengguna mengklik tombol 'Block' tombol. Jika ini aplikasi web Anda tidak akan bisa meminta izin dari pengguna lagi. Mereka harus "buka pemblokiran" secara manual aplikasi Anda dengan mengubah status izinnya, yang tersembunyi di panel setelan. Pikirkan baik-baik tentang bagaimana dan kapan Anda meminta izin dari pengguna, karena jika mereka mengeklik blokir, itu bukan cara mudah untuk membatalkan keputusan itu.
Kabar baiknya adalah sebagian besar pengguna dapat memberikan izin selama mereka tahu alasan permintaan izin tersebut.
Kita akan melihat bagaimana beberapa situs populer meminta izin nanti.
Menyertakan pengguna dengan PushManager
Setelah kita mendaftarkan pekerja layanan dan mendapatkan izin, kita dapat membuat pengguna berlangganan dengan
memanggil registration.pushManager.subscribe()
.
function subscribeUserToPush() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
),
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function (pushSubscription) {
console.log(
'Received PushSubscription: ',
JSON.stringify(pushSubscription),
);
return pushSubscription;
});
}
Saat memanggil metode subscribe()
, kita meneruskan objek options, yang terdiri dari
parameter wajib dan opsional.
Mari kita lihat semua opsi yang bisa kita berikan.
Opsi userVisibleOnly
Ketika push pertama kali ditambahkan ke browser, ada ketidakpastian tentang apakah developer harus dapat mengirim pesan push dan tidak menampilkan notifikasi. Ini biasanya disebut sebagai {i>push<i}, karena pengguna tidak mengetahui bahwa sesuatu telah terjadi di latar belakang.
Masalahnya, pengembang dapat melakukan hal-hal buruk seperti melacak lokasi pengguna di secara berkelanjutan tanpa disadari oleh pengguna.
Untuk menghindari skenario ini dan memberikan waktu kepada penulis spesifikasi untuk mempertimbangkan cara terbaik dalam mendukung permintaan ini
fitur, opsi userVisibleOnly
ditambahkan dan meneruskan nilai true
adalah
perjanjian dengan browser bahwa aplikasi web akan menampilkan notifikasi setiap kali push
diterima (yaitu, tanpa push senyap).
Saat ini Anda harus meneruskan nilai true
. Jika Anda tidak menyertakan
Kunci userVisibleOnly
atau meneruskan false
Anda akan mendapatkan error berikut:
Chrome saat ini hanya mendukung Push API untuk langganan yang akan menghasilkan
pesan yang terlihat oleh pengguna. Anda dapat menunjukkannya
dengan memanggil
Sebagai gantinya, pushManager.subscribe({userVisibleOnly: true})
. Lihat
https://goo.gl/yqv4Q4 untuk mengetahui detail selengkapnya.
Saat ini, fitur ini terlihat seperti push diam-diam yang tidak akan pernah diterapkan di Chrome. Sebagai gantinya, penulis spesifikasi sedang mempelajari gagasan API anggaran yang akan memungkinkan aplikasi web jumlah pesan push senyap berdasarkan penggunaan aplikasi web.
Opsi applicationServerKey
Kita sempat menyebutkan "kunci server aplikasi" di bagian sebelumnya. "Aplikasi kunci server" digunakan oleh layanan {i>push<i} untuk mengidentifikasi aplikasi yang membuat pengguna berlangganan dan memastikan bahwa aplikasi yang sama memberitahu pengguna tersebut.
Kunci server aplikasi adalah pasangan kunci publik dan pribadi yang unik untuk aplikasi Anda. Kunci pribadi harus dirahasiakan untuk aplikasi Anda dan kunci publik dapat dibagikan dengan bebas.
Opsi applicationServerKey
yang diteruskan ke panggilan subscribe()
merupakan akses publik
tombol. Browser meneruskan ini ke layanan {i>push<i} ketika membuat pengguna berlangganan, yang berarti {i>push<i}
layanan Anda dapat mengaitkan kunci publik aplikasi Anda ke PushSubscription
pengguna.
Diagram di bawah menggambarkan langkah-langkah ini.
- Aplikasi web Anda dimuat di browser dan Anda memanggil
subscribe()
, yang meneruskan kunci server aplikasi. - Browser kemudian membuat permintaan jaringan ke layanan {i>push<i} yang akan menghasilkan endpoint, mengaitkan endpoint ini dengan kunci publik aplikasi dan mengembalikan endpoint ke browser.
- Browser akan menambahkan endpoint ini ke
PushSubscription
, yang ditampilkan melalui Janjisubscribe()
.
Jika nanti Anda ingin mengirim pesan push, Anda harus membuat header Authorization yang akan berisi informasi yang ditandatangani dengan kunci pribadi server aplikasi Anda. Jika layanan push menerima permintaan untuk mengirimkan pesan push, layanan ini dapat memvalidasi header Authorization yang ditandatangani ini dengan mencari kunci publik yang ditautkan ke titik akhir yang menerima permintaan. Jika tanda tangan tersebut valid, layanan push tahu bahwa layanan itu harus berasal dari server aplikasi dengan kunci pribadi yang cocok. Pada dasarnya, hal ini adalah langkah pengamanan yang mencegah orang lain mengirim email pesan ke pengguna aplikasi.
Secara teknis, applicationServerKey
bersifat opsional. Namun, cara termudah
di Chrome memerlukannya, dan browser lain mungkin memerlukannya di
masa depan. Setelan ini opsional di Firefox.
Spesifikasi yang menentukan apa kunci server aplikasi yang seharusnya spesifikasi VAPID. Setiap kali Anda membaca sesuatu yang mengacu pada "kunci server aplikasi" atau "Kunci VAPID", tetapi ingat bahwa keduanya sama.
Cara membuat kunci server aplikasi
Anda dapat membuat rangkaian kunci server aplikasi publik dan pribadi dengan mengunjungi web-push-codelab.glitch.me atau Anda dapat menggunakan class command line web-push cara membuat kunci dengan melakukan hal berikut:
$ npm install -g web-push
$ web-push generate-vapid-keys
Anda hanya perlu membuat kunci ini satu kali untuk aplikasi, tetapi pastikan Anda menyimpan kunci pribadi. (Ya, saya baru saja mengatakan itu.)
Izin dan subscribe()
Ada satu efek samping dari memanggil subscribe()
. Jika aplikasi web Anda tidak memiliki izin untuk
menampilkan notifikasi pada saat memanggil subscribe()
, browser akan meminta
izin untuk Anda. Hal ini berguna jika UI Anda berfungsi dengan alur ini, tetapi jika Anda ingin cara lainnya
mengontrol (dan saya pikir sebagian besar developer akan melakukannya), tetap berpegang pada Notification.requestPermission()
API
yang kita gunakan sebelumnya.
Apa itu PushSubscription?
Kita memanggil subscribe()
, meneruskan beberapa opsi, dan sebagai gantinya, kita mendapatkan promise yang di-resolve menjadi
PushSubscription
menghasilkan beberapa kode seperti berikut:
function subscribeUserToPush() {
return navigator.serviceWorker
.register('/service-worker.js')
.then(function (registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(
'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
),
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function (pushSubscription) {
console.log(
'Received PushSubscription: ',
JSON.stringify(pushSubscription),
);
return pushSubscription;
});
}
Objek PushSubscription
berisi semua informasi yang diperlukan untuk mengirim push
pesan ke pengguna tersebut. Jika Anda mencetak konten menggunakan JSON.stringify()
, Anda akan melihat
berikut ini:
{
"endpoint": "https://some.pushservice.com/something-unique",
"keys": {
"p256dh":
"BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
"auth":"FPssNDTKnInHVndSTdbKFw=="
}
}
endpoint
adalah URL layanan push. Untuk memicu pesan push, buat permintaan POST
ke URL ini.
Objek keys
berisi nilai yang digunakan untuk mengenkripsi data pesan yang dikirim dengan pesan push
(yang akan kita bahas nanti di bagian ini).
Berlangganan lagi secara rutin untuk mencegah akhir masa berlaku
Saat berlangganan notifikasi push, Anda sering menerima PushSubscription.expirationTime
dari null
. Secara teori, hal ini berarti langganan tidak akan pernah berakhir (berbeda dengan saat Anda menerima DOMHighResTimeStamp
, yang memberi tahu Anda waktu persisnya saat langganan berakhir). Namun dalam praktiknya, umumnya browser masih membiarkan masa berlaku langganan berakhir, misalnya, jika tidak ada notifikasi push yang diterima untuk waktu yang lebih lama, atau jika browser mendeteksi bahwa pengguna tidak menggunakan aplikasi yang memiliki izin notifikasi push. Salah satu pola untuk mencegah hal ini adalah dengan membuat pengguna berlangganan kembali pada setiap notifikasi yang diterima, seperti yang ditunjukkan dalam cuplikan berikut. Ini mengharuskan Anda untuk mengirim notifikasi cukup sering bagi browser agar tidak mengundurkan diri secara otomatis dari langganan, dan Anda harus mempertimbangkan dengan cermat kelebihan dan kekurangan notifikasi yang sah terhadap pengiriman spam kepada pengguna secara tidak sengaja hanya agar langganan tidak kedaluwarsa. Pada akhirnya, Anda tidak boleh mencoba melawan browser dalam upayanya untuk melindungi pengguna dari langganan notifikasi yang sudah lama terlupakan.
/* In the Service Worker. */
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
// Display notification or handle data
// Example: show a notification
const title = 'New Notification';
const body = 'You have new updates!';
const icon = '/images/icon.png';
const tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
// Attempt to resubscribe after receiving a notification
event.waitUntil(resubscribeToPush());
});
function resubscribeToPush() {
return self.registration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.then(function() {
return self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
});
})
.then(function(subscription) {
console.log('Resubscribed to push notifications:', subscription);
// Optionally, send new subscription details to your server
})
.catch(function(error) {
console.error('Failed to resubscribe:', error);
});
}
Mengirim langganan ke Server Anda
Setelah memiliki langganan push, Anda pasti ingin mengirimkannya ke server. Terserah Anda bagaimana
lakukan itu, tetapi tip kecilnya adalah menggunakan JSON.stringify()
untuk mengeluarkan semua data yang diperlukan
langganan. Atau, Anda bisa membuat kumparan yang sama
secara manual seperti berikut:
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.getKeys('p256dh'),
auth: pushSubscription.getKeys('auth'),
},
};
// The above is the same output as:
const subscriptionObjectToo = JSON.stringify(pushSubscription);
Pengiriman langganan dilakukan di halaman web seperti berikut:
function sendSubscriptionToBackEnd(subscription) {
return fetch('/api/save-subscription/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(subscription),
})
.then(function (response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function (responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
Server node menerima permintaan ini dan menyimpan datanya ke database untuk digunakan nanti.
app.post('/api/save-subscription/', function (req, res) {
if (!isValidSaveRequest(req, res)) {
return;
}
return saveSubscriptionToDatabase(req.body)
.then(function (subscriptionId) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({data: {success: true}}));
})
.catch(function (err) {
res.status(500);
res.setHeader('Content-Type', 'application/json');
res.send(
JSON.stringify({
error: {
id: 'unable-to-save-subscription',
message:
'The subscription was received but we were unable to save it to our database.',
},
}),
);
});
});
Dengan detail PushSubscription
di server, siap untuk mengirim
pesan kapan pun kita mau.
Berlangganan lagi secara rutin untuk mencegah akhir masa berlaku
Saat berlangganan notifikasi push, Anda sering menerima PushSubscription.expirationTime
dari null
. Secara teori, hal ini berarti langganan tidak akan pernah berakhir (berbeda dengan saat Anda menerima DOMHighResTimeStamp
, yang memberi tahu Anda waktu persisnya saat langganan berakhir). Namun dalam praktiknya, umumnya browser masih membiarkan masa berlaku langganan berakhir, misalnya, jika tidak ada notifikasi push yang diterima dalam waktu lama, atau jika browser mendeteksi bahwa pengguna tidak menggunakan aplikasi yang memiliki izin notifikasi push. Salah satu pola untuk mencegah hal ini adalah dengan membuat pengguna berlangganan kembali pada setiap notifikasi yang diterima, seperti yang ditunjukkan dalam cuplikan berikut. Ini mengharuskan Anda untuk mengirim notifikasi cukup sering bagi browser agar masa berlaku langganan tidak berakhir secara otomatis, dan Anda harus mempertimbangkan dengan cermat kelebihan dan kekurangan notifikasi yang sah terhadap permintaan spam kepada pengguna agar langganan tidak kedaluwarsa. Pada akhirnya, Anda tidak boleh mencoba melawan browser dalam upayanya untuk melindungi pengguna dari langganan notifikasi yang sudah lama terlupakan.
/* In the Service Worker. */
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
// Display notification or handle data
// Example: show a notification
const title = 'New Notification';
const body = 'You have new updates!';
const icon = '/images/icon.png';
const tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
// Attempt to resubscribe after receiving a notification
event.waitUntil(resubscribeToPush());
});
function resubscribeToPush() {
return self.registration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.then(function() {
return self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
});
})
.then(function(subscription) {
console.log('Resubscribed to push notifications:', subscription);
// Optionally, send new subscription details to your server
})
.catch(function(error) {
console.error('Failed to resubscribe:', error);
});
}
FAQ
Beberapa pertanyaan umum yang diajukan orang pada tahap ini:
Dapatkah saya mengubah layanan push yang digunakan browser?
Tidak. Layanan push dipilih oleh browser dan seperti yang kita lihat pada
Panggilan subscribe()
, browser akan membuat permintaan jaringan ke layanan push
untuk mengambil detail yang membentuk PushSubscription.
Setiap browser menggunakan Layanan Push yang berbeda, bukankah API-nya berbeda?
Semua layanan push akan mengharapkan API yang sama.
API umum ini disebut Protokol Push Web dan menjelaskan permintaan jaringan yang harus dibuat aplikasi Anda untuk memicu pesan push.
Jika saya membuat pengguna berlangganan melalui desktop, apakah mereka juga berlangganan di ponsel?
Sayangnya tidak. Pengguna harus mendaftar untuk push di setiap browser yang ingin menerima pesan. Perlu juga dicatat bahwa ini akan membutuhkan pengguna yang memberikan izin akses di setiap perangkat.
Langkah berikutnya
- Ringkasan Notifikasi Push Web
- Cara Kerja Push
- Berlangganan Pengguna
- UX Izin
- Mengirim Pesan dengan Library Web Push
- Protokol Push Web
- Menangani Peristiwa Push
- Menampilkan Notifikasi
- Perilaku Notifikasi
- Pola Notifikasi Umum
- FAQ Notifikasi Push
- Masalah Umum dan Melaporkan Bug