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#.