1. Обзор
Push-сообщения обеспечивают простой и эффективный способ повторного взаимодействия с вашими пользователями. В этой лаборатории кода вы узнаете, как добавлять push-уведомления в свое веб-приложение.
Что вы узнаете
- Как подписаться и отписаться пользователя на push-рассылку
- Как обрабатывать входящие push-сообщения
- Как отобразить уведомление
- Как реагировать на клики по уведомлениям
Что вам понадобится
- Chrome 52 или выше
- Веб-сервер для Chrome или ваш собственный веб-сервер по выбору
- Текстовый редактор
- Базовые знания HTML, CSS, JavaScript и Chrome DevTools.
- Пример кода (см. раздел «Настройка»).
2. Настройте
Загрузите пример кода
Получить пример кода для этой лаборатории кода можно двумя способами:
- Клонируйте репозиторий Git:
git clone https://github.com/GoogleChrome/push-notifications.git
- Загрузите ZIP-файл:
Если вы загрузите исходный код в виде ZIP-файла, при его распаковке вы получите корневую папку push-notifications-master
.
Установите и проверьте веб-сервер
Хотя вы можете использовать собственный веб-сервер, эта лаборатория кода разработана для хорошей работы с приложением «Веб-сервер для Chrome». Если это приложение еще не установлено, его можно загрузить из Интернет-магазина Chrome:
После установки приложения «Веб-сервер для Chrome» нажмите ярлык «Приложения» на панели закладок:
В окне «Приложения» щелкните значок «Веб-сервер»:
Далее вы увидите это диалоговое окно, которое позволит вам настроить локальный веб-сервер:
Нажмите кнопку «Выбрать папку» и выберите папку app
в загруженной папке push-notifications
. Это позволяет вам обслуживать незавершенную работу через URL-адрес, указанный в разделе URL-адреса веб-сервера диалогового окна.
В разделе «Параметры» установите флажок «Автоматически показывать index.html» , как показано ниже:
Затем остановите и перезапустите сервер, сдвинув переключатель «Веб-сервер: НАЧАЛО» влево, а затем обратно вправо.
Щелкните URL-адрес веб-сервера, чтобы посетить ваш сайт в веб-браузере. Вы должны увидеть страницу, которая выглядит следующим образом — хотя в вашей версии в качестве адреса может отображаться 127.0.0.1:8887:
Всегда обновляйте сервис-воркера
Во время разработки полезно следить за тем, чтобы ваш сервис-воркер всегда был в курсе последних изменений.
Чтобы настроить это в Chrome:
- Перейдите на вкладку Push Codelab .
- Откройте DevTools: Ctrl-Shift-I в Windows и Linux, Cmd-Option-I в macOS.
- Выберите панель «Приложения» , перейдите на вкладку «Сервисные работники» и установите флажок «Обновлять при перезагрузке» . Если этот флажок установлен, сервис-воркер принудительно обновляется каждый раз при перезагрузке страницы.
3. Зарегистрируйте сервис-воркера
Обратите внимание, что в каталоге вашего app
есть пустой файл с именем sw.js
Этот файл будет вашим сервис-воркером. Пока он может оставаться пустым. Вы добавите к нему код позже.
Во-первых, вам необходимо зарегистрировать этот файл в качестве вашего сервис-воркера.
Ваша страница app/index.html
загружает scripts/main.js
. Вы регистрируете своего сервис-воркера в этом файле JavaScript.
Добавьте следующий код в scripts/main.js
:
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push are supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
}
Этот код проверяет, поддерживаются ли вашим браузером сервисные работники и push-сообщения. Если они поддерживаются, код регистрирует ваш файл sw.js
Попробуйте это
Проверьте свои изменения, обновив вкладку Push Codelab в браузере.
Проверьте консоль в Chrome DevTools на Service Worker is registered message
, например:
Получить ключи сервера приложений
Для работы с этой кодовой лабораторией вам необходимо сгенерировать ключи сервера приложений. Вы можете сделать это на сопутствующем сайте: web-push-codelab.glitch.me.
Здесь вы можете сгенерировать пару открытого и закрытого ключей.
Скопируйте свой открытый ключ в scripts/main.js
заменив значение <Your Public Key>
:
const applicationServerPublicKey = '<Your Public Key>';
Важно: никогда не следует помещать свой закрытый ключ в свое веб-приложение!
4. Инициализация состояния
На данный момент кнопка «Включить » веб-приложения отключена, и ее нельзя нажать. Это связано с тем, что хорошей практикой является отключить кнопку по умолчанию и включить ее после того, как вы узнаете, что push-сообщения поддерживаются браузером, и вы сможете проверить, подписан ли пользователь в настоящее время на рассылку сообщений или нет.
Вам нужно будет создать две функции в scripts/main.js
:
-
initializeUI
, чтобы проверить, подписан ли пользователь в данный момент -
updateBtn
, чтобы включить вашу кнопку и изменить текст в зависимости от того, подписан пользователь или нет
Добавьте функцию initializeUI
в main.js
следующим образом:
function initializeUI() {
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
Ваш новый метод использует swRegistration
из предыдущего шага, получает из него свойство pushManager
и вызывает для него getSubscription()
.
pushManager
. getSubscription()
возвращает обещание, которое разрешается с текущей подпиской, если таковая имеется. В противном случае он возвращает null
. Благодаря этому вы можете проверить, подписан ли уже пользователь, установить значение isSubscribed
, а затем вызвать updateBtn()
чтобы обновить кнопку.
Добавьте функцию updateBtn()
в main.js
:
function updateBtn() {
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
Эта функция включает кнопку и меняет текст кнопки в зависимости от того, подписан пользователь или нет.
Последнее, что нужно сделать, это вызвать initializeUI()
, когда ваш сервис-воркер зарегистрирован в main.js
:
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
initializeUI();
})
Попробуйте это
Обновите вкладку Push Codelab . Вы должны увидеть, что кнопка «Включить push-сообщения» теперь включена (вы можете нажать ее), и вы должны увидеть, что User is NOT subscribed
в консоли.
По мере прохождения оставшейся части этой кодовой лаборатории вы должны видеть, что текст кнопки меняется каждый раз, когда вы подписываетесь или отписываетесь.
5. Подписать пользователя
На данный момент кнопка «Включить push-сообщения» мало что делает. Давайте это исправим.
В функции initializeUI()
добавьте прослушиватель кликов для вашей кнопки:
function initializeUI() {
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
// TODO: Unsubscribe user
} else {
subscribeUser();
}
});
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
updateSubscriptionOnServer(subscription);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
Когда пользователь нажимает кнопку, вы отключаете кнопку, чтобы убедиться, что пользователь не сможет нажать ее второй раз, поскольку подписка на push-сообщения может занять некоторое время.
Затем вы вызываете subscribeUser()
если пользователь в данный момент не подписан. Для этого вам нужно вставить следующий код в scripts/main.js
:
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(error) {
console.error('Failed to subscribe the user: ', error);
updateBtn();
});
}
Давайте рассмотрим, что делает этот код и как он подписывает пользователя на push-сообщения.
Сначала вы берете открытый ключ сервера приложений, который закодирован для URL-адресов Base64 , и преобразуете его в UInt8Array
, поскольку это ожидаемый входной сигнал вызова subscribe()
. Функция urlB64ToUint8Array()
находится в верхней части scripts/main.js
.
После преобразования значения вы вызываете метод subscribe()
в pushManager
вашего сервис-воркера, передавая открытый ключ вашего сервера приложений и значение userVisibleOnly: true
.
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
Параметр userVisibleOnly
гарантирует, что вы будете показывать уведомление каждый раз при отправке push-сообщения. В настоящее время это значение является обязательным и должно быть истинным.
Вызов subscribe()
возвращает обещание, которое будет разрешено после следующих шагов:
- Пользователь предоставил разрешение на отображение уведомлений.
- Браузер отправил сетевой запрос в службу push-уведомлений, чтобы получить данные, необходимые для создания
PushSubscription
.
Обещание subscribe()
будет разрешено с помощью PushSubscription
, если эти шаги были успешными. Если пользователь не предоставит разрешение или возникнут какие-либо проблемы с подпиской пользователя, обещание будет отклонено с ошибкой. Это дает вам следующую цепочку обещаний в вашей кодовой лаборатории:
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
updateBtn();
});
При этом вы либо получаете подписку и считаете пользователя подписанным, либо ловите ошибку и регистрируете ее в консоли. В обоих сценариях вы вызываете updateBtn()
чтобы убедиться, что кнопка снова включена и имеет соответствующий текст.
В реальном приложении функция updateSubscriptionOnServer()
позволяет отправлять данные о подписке на серверную часть, но для лаборатории кода вы просто отображаете подписку в своем пользовательском интерфейсе. Добавьте следующую функцию в scripts/main.js
:
function updateSubscriptionOnServer(subscription) {
// TODO: Send subscription to application server
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}
Попробуйте это
Перейдите на вкладку Push Codelab , обновите страницу и нажмите кнопку. Вы должны увидеть запрос на разрешение, подобный этому:
Если вы дадите разрешение, вы должны увидеть, User is subscribed
и вошёл в консоль. Текст кнопки изменится на «Отключить push-сообщения» , и вы сможете просмотреть подписку в виде данных JSON внизу страницы.
6. Разрешение на обработку отклонено
Одна вещь, которую вы еще не рассмотрели, — это то, что произойдет, если пользователь заблокирует запрос на разрешение. Это требует особого внимания, поскольку если пользователь заблокирует разрешение, ваше веб-приложение не сможет повторно отобразить запрос на разрешение и не сможет подписаться на пользователя. Вам нужно как минимум отключить кнопку, чтобы пользователь знал, что ее нельзя использовать.
Очевидное место для реализации этого сценария — функция updateBtn()
. Все, что вам нужно сделать, это проверить значение Notification.permission
, например:
function updateBtn() {
if (Notification.permission === 'denied') {
pushButton.textContent = 'Push Messaging Blocked';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;
}
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
Вы знаете, что если в разрешении denied
, пользователь не сможет подписаться, и вы больше ничего не сможете сделать, поэтому лучшим подходом является постоянное отключение кнопки.
Попробуйте это
Поскольку вы уже предоставили разрешение для своего веб-приложения на предыдущем шаге, вам нужно щелкнуть i в кружке в строке URL-адреса и изменить разрешение «Уведомления» на «Использовать глобальное значение по умолчанию» (Спросить) .
После изменения этого параметра обновите страницу, нажмите кнопку «Включить push-сообщения» и выберите «Блокировать» в диалоговом окне разрешений. Кнопка будет отключена, и на ней будет отображаться текст Push-сообщения заблокированы .
Благодаря этому изменению вы теперь можете подписаться на пользователя, позаботившись о возможных сценариях разрешений.
7. Обработка push-события
Прежде чем вы узнаете, как отправить push-сообщение из вашего бэкэнда, вам необходимо подумать, что на самом деле произойдет, когда подписанный пользователь получит push-сообщение.
Когда вы запускаете push-сообщение, браузер получает push-сообщение, определяет, для какого работника службы оно предназначено, пробуждает этого работника службы и отправляет событие push. Вам необходимо прослушать это событие и в результате отобразить уведомление.
Добавьте следующий код в файл sw.js
:
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
event.waitUntil(self.registration.showNotification(title, options));
});
Давайте пройдемся по этому коду. Вы прослушиваете push
события в своем сервис-воркере, добавляя прослушиватель событий:
self.addEventListener('push', ... );
(Если вы раньше не играли с веб-воркерами, self
, вероятно, является новым. В файле сервисного работника self
ссылается на самого сервисного работника.)
При получении push-сообщения будет вызван прослушиватель событий, и вы создадите уведомление, вызвав showNotification()
в registration
свойстве сервисного работника. showNotification()
требует title
; вы также можете предоставить ему объект options
, чтобы установить основное сообщение, значок и значок. (На момент написания значок использовался только на Android.)
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
self.registration.showNotification(title, options);
Последнее, что нужно учитывать при обработке push
событий, — это event.waitUntil()
. Этот метод принимает обещание, позволяющее браузеру поддерживать работу вашего сервис-воркера до тех пор, пока переданное обещание не будет выполнено.
Чтобы сделать приведенный выше код немного проще для понимания, вы можете переписать его так:
const notificationPromise = self.registration.showNotification(title, options);
event.waitUntil(notificationPromise);
Теперь, когда вы прошли через событие push, давайте проверим его.
Попробуйте это
Благодаря обработке push-событий в сервис-воркере вы можете запустить ложное push-событие, чтобы проверить, что происходит при получении сообщения.
В своем веб-приложении подпишитесь на push-сообщения и убедитесь, что в консоли User IS subscribed
. На панели приложений в DevTools на вкладке Service Workers нажмите кнопку «Нажать» :
После того, как вы нажмете «Push» , вы должны увидеть такое уведомление:
Примечание. Если этот шаг не сработал, попробуйте отменить регистрацию вашего сервисного работника с помощью ссылки «Отменить регистрацию» на панели приложений DevTools, дождитесь остановки сервисного работника, а затем перезагрузите страницу.
8. Нажмите на уведомление.
Если вы нажмете одно из этих уведомлений, вы заметите, что ничего не происходит. Вы можете обрабатывать клики уведомлений, прослушивая события notificationclick
в своем сервисном работнике.
Начните с добавления прослушивателя notificationclick
в sw.js
:
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click received.');
event.notification.close();
event.waitUntil(
clients.openWindow('https://developers.google.com/web')
);
});
Когда пользователь щелкает уведомление, будет вызван прослушиватель событий notificationclick
.
Код сначала закрывает уведомление, по которому было нажато:
event.notification.close();
Затем открывается новое окно или вкладка с загрузкой URL-адреса https://developers.google.com/web
. Не стесняйтесь изменить это.
event.waitUntil(
clients.openWindow('https://developers.google.com/web/')
);
event.waitUntil()
гарантирует, что браузер не завершит работу сервис-воркера до того, как будет отображено новое окно или вкладка.
Попробуйте это
Попробуйте еще раз вызвать push-сообщение в DevTools и щелкните уведомление. Теперь вы увидите закрытие уведомления и открытие новой вкладки.
9. Отправляйте push-сообщения
Вы видели, что ваше веб-приложение способно отображать уведомление с помощью DevTools, и узнали, как закрыть уведомление одним щелчком мыши. Следующим шагом является отправка фактического push-сообщения.
Обычно для этого требуется отправить подписку с веб-страницы на серверную часть. Затем серверная часть инициирует push-сообщение, выполнив вызов API к конечной точке подписки.
Это выходит за рамки данной лаборатории кода, но вы можете использовать сопутствующий сайт ( web-push-codelab.glitch.me ), чтобы вызвать фактическое push-сообщение. Вставьте подписку внизу страницы:
Затем вставьте это на сопутствующий сайт в текстовую область «Подписка на отправку» :
В разделе «Текст для отправки» добавьте любую строку, которую хотите отправить вместе с push-сообщением.
Нажмите кнопку «Отправить push-сообщение» .
После этого вы должны получить push-сообщение. Использованный вами текст будет записан в консоль.
Это должно дать вам возможность протестировать отправку и получение данных и, как результат, манипулировать уведомлениями.
Сопутствующее приложение — это всего лишь узел-сервер, который использует библиотеку веб-push для отправки сообщений. Стоит просмотреть организацию web-push-libs на GitHub, чтобы узнать, какие библиотеки доступны для отправки вам push-сообщений. Это обрабатывает множество деталей для запуска push-сообщений.
Вы можете увидеть весь код сопутствующего сайта здесь .
10. Отписать пользователя от подписки
Единственное, чего не хватает, — это возможности отписать пользователя от push-уведомлений. Для этого вам нужно вызвать unsubscribe()
в PushSubscription
.
Вернувшись в файл scripts/main.js
, измените прослушиватель кликов pushButton
в initializeUI()
на следующее:
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
unsubscribeUser();
} else {
subscribeUser();
}
});
Обратите внимание, что теперь вы собираетесь вызвать новую функцию unsubscribeUser()
. В этой функции вы получаете текущую подписку и вызываете для нее unsubscribe()
. Добавьте следующий код в scripts/main.js
:
function unsubscribeUser() {
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
});
}
Давайте пройдемся по этой функции.
Сначала вы получаете текущую подписку, вызывая getSubscription()
:
swRegistration.pushManager.getSubscription()
Это возвращает обещание, которое разрешается с помощью PushSubscription
, если таковое существует; в противном случае возвращается null
. Если есть подписка, вы вызываете для нее unsubscribe()
, что делает PushSubscription
недействительным.
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
// TODO: Tell application server to delete subscription
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
Вызов unsubscribe()
возвращает обещание, поскольку его выполнение может занять некоторое время. Вы возвращаете это обещание, поэтому следующий then()
в цепочке ожидает завершения unsubscribe()
. Вы также добавляете обработчик catch на случай, если вызов unsubscribe()
приведет к ошибке. После этого вы можете обновить свой пользовательский интерфейс.
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
})
Попробуйте это
У вас должна быть возможность нажать «Включить push-сообщения» или «Отключить push-сообщения» в вашем веб-приложении, и журналы будут показывать, что пользователь подписан и отписан от подписки.
11. Готово
Поздравляем с завершением этой лаборатории!
В этой лаборатории кода показано, как начать работу с добавлением push-уведомлений в ваше веб-приложение. Если вы хотите узнать больше о возможностях веб-уведомлений, ознакомьтесь с этими документами .
Если вы хотите разместить push-уведомления на своем сайте, вас может заинтересовать добавление поддержки старых браузеров или браузеров, не соответствующих стандартам, которые используют GCM. Узнайте больше здесь .
Дальнейшее чтение
- Веб-push-уведомление : документация по основам веб-технологий.
- Библиотеки веб-push : библиотеки веб-push, включая Node.js, PHP, Java, Python, C и C#.