1. Обзор
Push-уведомления — это простой и эффективный способ возобновить взаимодействие с пользователями. В этом практическом занятии вы узнаете, как добавить push-уведомления в ваше веб-приложение.
Что вы узнаете
- Как подписаться и отписаться от push-уведомлений для пользователя
- Как обрабатывать входящие push-сообщения
- Как отобразить уведомление
- Как реагировать на клики по уведомлениям
Что вам понадобится
- Chrome 52 или выше
- Веб-сервер для Chrome или ваш собственный веб-сервер по вашему выбору.
- Текстовый редактор
- Базовые знания HTML, CSS, JavaScript и инструментов разработчика Chrome.
- Пример кода (см. раздел «Настройка»).
2. Настройка
Скачать пример кода
Пример кода для этого практического занятия можно получить двумя способами:
- Клонируйте репозиторий Git:
git clone https://github.com/GoogleChrome/push-notifications.git
- Скачать ZIP-файл:
Если вы скачаете исходный код в виде ZIP-файла, после его распаковки вы получите корневую папку push-notifications-master .
Установите и проверьте веб-сервер.
Хотя вы можете использовать собственный веб-сервер, этот практический пример разработан для корректной работы с приложением Web Server for Chrome. Если у вас еще не установлено это приложение, вы можете загрузить его из Chrome Web Store:
После установки приложения «Веб-сервер для Chrome» нажмите на ярлык «Приложения» на панели закладок:

В окне «Приложения» щелкните значок «Веб-сервер»:

Далее вы увидите диалоговое окно, позволяющее настроить локальный веб-сервер:

Нажмите кнопку «Выбрать папку» и выберите папку app в загруженной папке push-notifications . Это позволит вам отправлять уведомления о разрабатываемом приложении по URL-адресу, указанному в разделе «URL-адреса веб-сервера» диалогового окна.
В разделе «Параметры» установите флажок рядом с пунктом «Автоматически показывать index.html» , как показано ниже:

Затем остановите и перезапустите сервер, переместив переключатель «Веб-сервер: ЗАПУЩЕН» влево, а затем обратно вправо.

Щёлкните по URL-адресу веб-сервера, чтобы открыть свой сайт в веб-браузере. Вы должны увидеть страницу, которая выглядит примерно так — хотя в вашей версии в качестве адреса может отображаться 127.0.0.1:8887:

Всегда сообщайте о состоянии сервисного работника.
В процессе разработки полезно убедиться, что ваш сервисный работник всегда в курсе последних изменений.
Чтобы настроить это в Chrome:
- Перейдите на вкладку Push Codelab .
- Откройте инструменты разработчика: 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 на наличие Service Worker is registered message , примерно такого вида:

Получить ключи сервера приложений
Для работы с этим практическим заданием вам необходимо сгенерировать ключи сервера приложений. Сделать это можно на сопутствующем сайте: web-push-codelab.glitch.me
Здесь вы можете сгенерировать пару открытого и закрытого ключей.

Скопируйте свой открытый ключ в scripts/main.js , заменив значение <Your Public Key> :
const applicationServerPublicKey = '<Your Public Key>';
Важно: ни в коем случае нельзя размещать закрытый ключ в веб-приложении!
4. Инициализация состояния
В данный момент кнопка «Включить» в веб-приложении отключена и недоступна для нажатия. Это связано с тем, что рекомендуется отключать кнопку push-уведомлений по умолчанию и включать её только после того, как будет подтверждена поддержка push-уведомлений браузером и возможность проверки подписки пользователя на рассылку.
Вам потребуется создать две функции в scripts/main.js :
-
initializeUI— проверка наличия у пользователя текущей подписки. -
updateBtn, чтобы активировать кнопку и изменять текст в зависимости от того, подписан пользователь на рассылку или нет.
Добавьте в main.js функцию initializeUI следующим образом:
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-уведомления.
Сначала вы берёте открытый ключ сервера приложений, закодированный в формате Base64, безопасном для использования с URL-адресами , и преобразуете его в UInt8Array , поскольку это ожидаемый входной параметр для вызова функции subscribe() . Функция urlB64ToUint8Array() находится в верхней части scripts/main.js .
После преобразования значения вызовите метод subscribe() объекта pushManager вашего сервис-воркера, передав в него открытый ключ вашего сервера приложений и значение userVisibleOnly: true .
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
Параметр userVisibleOnly гарантирует, что уведомление будет отображаться каждый раз, когда отправляется push-уведомление. В настоящее время это значение является обязательным и должно быть true.
Вызов метода 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» в кружке в адресной строке и изменить разрешение «Уведомления» на «Использовать глобальные настройки по умолчанию (Запрашивать)» .

После изменения этой настройки обновите страницу, нажмите кнопку «Включить push-уведомления» и выберите «Блокировать» в диалоговом окне разрешений. Кнопка будет неактивна, и отобразится текст «Push-уведомления заблокированы» .

Благодаря этому изменению теперь можно подписать пользователя, предварительно учтя все возможные сценарии предоставления прав доступа.
7. Обработка события 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', ... );
(Если вы раньше не работали с Web Workers, 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-уведомления и убедитесь, что в консоли отображается User IS subscribed ». В панели «Приложение» в инструментах разработчика, на вкладке «Service Workers» , нажмите кнопку «Push» :

После нажатия кнопки «Push» вы должны увидеть уведомление примерно такого вида:

Примечание: Если этот шаг не сработает, попробуйте отменить регистрацию вашего сервис-воркера с помощью ссылки «Отменить регистрацию» на панели инструментов разработчика, дождитесь остановки сервис-воркера, а затем перезагрузите страницу.
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-уведомление в Инструментах разработчика и нажмите на него. Теперь вы увидите, как уведомление закроется и откроется новая вкладка.
9. Отправка push-уведомлений
Вы уже убедились, что ваше веб-приложение способно отображать уведомления с помощью инструментов разработчика, и изучили, как закрыть уведомление одним щелчком мыши. Следующий шаг — отправить фактическое push-уведомление.
Обычно для этого требуется отправить подписку с веб-страницы на бэкэнд. Затем бэкэнд инициирует отправку push-уведомления, выполнив вызов API к конечной точке, указанной в подписке.
Это выходит за рамки данного практического занятия, но вы можете использовать сопутствующий сайт ( web-push-codelab.glitch.me ), чтобы отправить реальное push-уведомление. Вставьте ссылку на подписку внизу страницы:

Затем вставьте этот текст на сопутствующий сайт в текстовое поле «Подписка для отправки» :

В поле «Текст для отправки» добавьте любую строку, которую хотите отправить вместе с push-уведомлением.
Нажмите кнопку «Отправить push-уведомление» .

После этого вы должны получить push-уведомление. Введенный вами текст будет записан в консоль.

Это даст вам возможность протестировать отправку и получение данных, а также настроить уведомления.
Сопутствующее приложение представляет собой всего лишь сервер Node.js, использующий библиотеку web-push для отправки сообщений. Стоит ознакомиться с репозиторием web-push-libs на GitHub, чтобы узнать, какие библиотеки доступны для отправки push-уведомлений. Эта библиотека обрабатывает множество деталей, необходимых для запуска push-уведомлений.
10. Отписаться от пользователя
Единственное, чего не хватает, — это возможности отписаться пользователя от рассылки. Для этого необходимо вызвать 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-уведомления» , и в логах отобразится информация о том, был ли пользователь подписан или отписан.

11. Завершено
Поздравляем с завершением этого практического занятия!
В этом практическом занятии показано, как начать работу с добавлением push-уведомлений в ваше веб-приложение. Если вы хотите узнать больше о возможностях веб-уведомлений, ознакомьтесь с этими документами .
Если вы хотите использовать push-уведомления на своем сайте, вам может быть полезно добавить поддержку старых браузеров или браузеров, не соответствующих стандартам, но использующих GCM. Подробнее можно узнать здесь .
Дополнительная информация
- Веб-push-уведомления : документация по основам веб-технологий.
- Библиотеки для веб-push-уведомлений : библиотеки для веб-push-уведомлений, включая Node.js, PHP, Java, Python, C и C#.