Push-уведомление на вашем сайте

В предыдущей статье мы создали наш первый PWA, но не видели всей концепции. Удобство PWA заключается в том, что он может работать как мобильное приложение, устанавливаться на телефон, управлять автономным режимом и особенно отправлять push-уведомления. Уведомления являются важным элементом взаимодействия с пользователем, они позволяют отправлять напоминания и общаться с нашими пользователями. Мы собираемся завершить последнее руководство, настроив простую систему push-уведомлений, используя Firebase для хранения токенов пользователей.

Чтобы ускориться, мы приглашаем вас наверстать упущенное, загрузив проект https://github.com/CaptainJojo/pwa-parisjs, который содержит готовый к работе PWA.

git clone https://github.com/CaptainJojo/pwa-parisjs
cd pwa-parisjs
git checkout manifest
npm install
npm start

На этом этапе у вас должен быть доступ к вашему PWA по адресу localhost: 8080. Если вы еще этого не сделали, вам необходимо установить Lighthouse, это позволит вам убедиться, что у вас есть PWA.

Прежде чем приступить к отправке push-уведомлений, мы собираемся выполнить настройку. Да! Это не волшебство, мы будем запрашивать авторизацию у Google.

Заходим в Firebase для создания проекта.

Не стесняйтесь выбирать для проекта любое название. Как только вы окажетесь на приборной панели, вам нужно щелкнуть маленькое колесико, а затем «Настройки проекта».

На вкладке «Облачные сообщения» вы найдете свой идентификатор отправителя.

В manifest.json, доступном в общей папке приложения, вы должны добавить в конец файла «gsm_sender_id» со значением идентификатора отправителя.

{
  "name": "Lemonde",
  "short_name": "Lemonde",
  "icons": [{
        "src": "images/touch/icon-128x128.png",
        "sizes": "128x128",
        "type": "image/png"
      }, {
        "src": "images/touch/apple-touch-icon.png",
        "sizes": "152x152",
        "type": "image/png"
      }, {
        "src": "images/touch/ms-touch-icon-144x144-precomposed.png",
        "sizes": "144x144",
        "type": "image/png"
      }, {
        "src": "images/touch/chrome-touch-icon-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
      }],
  "start_url": "/",
  "display": "standalone",
  "background_color": "#3E4EB8",
  "theme_color": "#2F3BA2",
  "gcm_sender_id": "309914158916"
}

Теперь мы попросим пользователя принять уведомления. Это очень просто, вам нужно только добавить следующий код в файл public / register.js:

if('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function() {
      return navigator.serviceWorker.ready;
    }).then(function(registration) {
      registration.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) {
        var endpointSections = sub.endpoint.split('/');
        var subscriptionId = endpointSections[endpointSections.length - 1];
        console.log('endpoint:', subscriptionId);
      });
    });
  navigator.serviceWorker.ready.then(function(registration) {
     console.log('Service Worker Ready');
  });
}

Как и следовало ожидать, если вы перезапустите сервер, у вас будет запрос на принятие уведомлений.

Вы также должны увидеть в консоли такое сообщение:

endpoint: cV2kP3sOb24:APA91bHfZgFSPQ3CXyG9LejWdq9jOT-WqQpvK4peX9ZZtrfsHCf6OPEvDegjsTF3uXj-Qsf4jOJ5O8rwdEm9fjKZbqerzcZUjDmsiaRcqmxuOOkpuEqPca31Dlh-6g0YgkvnLccIPz_Z

Это токен устройства, мы будем использовать его для отправки push-уведомления.

Поскольку мы хотим сделать что-то чистое (даже если это просто учебник), мы собираемся использовать Firebase для хранения токенов пользователей. Для этого вернемся в консоль Firebase и нажмем «Веб-настройка» на вкладке «Аутентификация».

Установка скрипта выполняется в HTML-коде в файлах public / home.html и public / article / alorscettearticle.html.

<html>
  <head>
    <meta charset=utf-8/>
    <meta name="theme-color" content="#2F3BA2">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="manifest" href="/manifest.json">
  </head>
  <body>
    <script src="https://www.gstatic.com/firebasejs/3.5.2/firebase.js"></script>
    <script src="/register.js"></script>
    <link rel="stylesheet" href="/main.css">
    <link rel="stylesheet" href="/async.css">

Инициализация идет в public / register.js.

// Initialize Firebase
var config = {
  apiKey: "AIzaSyCGg4NPckoKkYdGlZeNHbRAnnK-jLhEPjY",
  authDomain: "pwa-parisjs.firebaseapp.com",
  databaseURL: "https://pwa-parisjs.firebaseio.com",
  storageBucket: "pwa-parisjs.appspot.com",
  messagingSenderId: "309914158916"
};
firebase.initializeApp(config);
if('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function() {
      return navigator.serviceWorker.ready;
    }).then(function(registration) {
      registration.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) {
        var endpointSections = sub.endpoint.split('/');
        var subscriptionId = endpointSections[endpointSections.length - 1];
        console.log('endpoint:', subscriptionId);
      });
    });
  navigator.serviceWorker.ready.then(function(registration) {
     console.log('Service Worker Ready');
  });
}

Теперь, когда Firebase установлена, мы должны сохранить токен пользователя в «базе данных». Вы найдете всю необходимую помощь в документации Firebase.

Итак, мы собираемся добавить файл public / register.js

// Initialize Firebase
var config = {
  apiKey: "AIzaSyCGg4NPckoKkYdGlZeNHbRAnnK-jLhEPjY",
  authDomain: "pwa-parisjs.firebaseapp.com",
  databaseURL: "https://pwa-parisjs.firebaseio.com",
  storageBucket: "pwa-parisjs.appspot.com",
  messagingSenderId: "309914158916"
};
firebase.initializeApp(config);
if('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function() {
      return navigator.serviceWorker.ready;
    }).then(function(registration) {
      registration.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) {
        var endpointSections = sub.endpoint.split('/');
        var subscriptionId = endpointSections[endpointSections.length - 1];
        var newKey = firebase.database().ref().child('token').push().key;
        firebase.database().ref('token/' + newKey).set({subscriptionId: subscriptionId});
        console.log('endpoint:', subscriptionId);
      });
    });
  navigator.serviceWorker.ready.then(function(registration) {
     console.log('Service Worker Ready');
  });
}

Перед запуском сервера вы должны открыть разрешения для Firebase, чтобы он мог писать в базу данных. Во вкладке «База данных» - ›« Правила »необходимо указать:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

Если вы перезапустите сервер, вы увидите токен, хранящийся в БД, на вкладке «База данных» Firebase.

Теперь, когда токены хранятся в базе данных, мы собираемся подготовить сообщение, которое появится при появлении push-уведомления. Добавим в файл public / sw.js следующий код:

console.log('Started', self);
self.addEventListener('install', function(event) {
  self.skipWaiting();
  console.log('Installed', event);
});
self.addEventListener('activate', function(event) {
  console.log('Activated', event);
});
self.addEventListener('push', function(event) {
  console.log('Push message', event);
  var title = 'Le push de test :)';
  event.waitUntil(
    self.registration.showNotification(title, {
     body: 'Bravo tu l\'as reçu',
     icon: 'images/icon.png',
     tag: 'my-tag'
   }));
});

Почти готово! Мы собираемся создать URL-адрес «/ sender», который позволит нам отправлять уведомления для всех токенов, которые у нас есть в базе данных. Для этого мы собираемся использовать модули request и firebase (версия npm). Вот новый package.json:

{
  "name": "pwa-parisjs",
  "version": "0.0.1",
  "description": "A Progressive Web App",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "sw": "gulp sw-precache"
  },
  "dependencies": {
    "express": "^4.14.0",
    "firebase": "^3.5.1",
    "request": "^2.75.0"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "sw-precache": "^3.2.0"
  }
}

В файле app.js мы инициализируем Firebase. Вам понадобится файл ключа сервера. Щелкните колесо в Firebase, а затем «Разрешения». Теперь вы попали на другую консоль.

В «Учетные записи служб» создайте новую учетную запись.

Будет загружен файл json, вам необходимо добавить его в папку вашего проекта.

В файле app.js мы собираемся добавить маршрут / отправителя, который будет отправлять запрос push-уведомления со всеми токенами.

var path = require('path');
var express = require('express');
var app = express();
var firebase = require('firebase');
var request = require('request');
firebase.initializeApp({
  databaseURL: 'https://pwa-parisjs.firebaseio.com/', // To be found in the Database tab
  serviceAccount: 'pwa-parisjs-cf0bc079ee69.json' // Name of the json file at the root of your app folder
});
app.use(express.static(path.join(__dirname, 'public'), {index: false}))
app.get('/sender', function(req, res){
  var allToken = firebase.database().ref('/token');
  Promise.all([allToken.once('value')]).then(function(resp) {
    var allToken = resp[0].val();
    tokenRep = '';
    Object.keys(allToken).forEach(function(uid) {
      var token = allToken[uid];
      request({
        url: 'https://android.googleapis.com/gcm/send',
        method: 'POST',
        headers: {
          'Content-Type' :' application/json',
          'Authorization': 'key=AIzaSyDV-KhCa9dM-bSg_r23GUwpRJqBw6qrJIc', // Server key available in the parameters of the Firebase project
        },
        body: JSON.stringify(
          {
            "registration_ids" : [token.subscriptionId]
          }
        )
      }, function(error, response, body) {
      });
    });
  }).catch(function(error) {
    console.log('Failed to start weekly top posts emailer:', error);
  });
  res.send('ok');
});

app.use('/', function (req, res) {
  res.sendFile(__dirname + '/public/home.html');
});
app.listen(8080, function () {
  console.log('Example app listening on port 8080!');
});

Будь осторожен! Ключ авторизации находится на первой вкладке, которую мы открыли.

Если все в порядке, при перезапуске сервера и переходе в / а затем / отправитель вы получите уведомление. Если это не так, очистите кеш приложения в консоли Chrome.

Еще раз, этот код - всего лишь учебник, я приглашаю вас открывать вопросы по любому вопросу. Финальный код доступен здесь.

Статья переведена с французского Мари Готье

Автор: Джонатан Джалузот
Twitter: Джонатан Джалузо