Як перетворити WebApp на PWA за допомогою Push-повідомлення

У цій статті ми побачимо, як перетворити веб-програму або веб-сайт на PWA за допомогою Push-повідомлення за допомогою Firebase Cloud Messaging.

У сучасному світі більшість веб-додатків перетворюються на PWA (прогресивний веб-додаток), оскільки він надає такі функції, як підтримка офлайн, push-повідомлення, фонова синхронізація. Функції PWA роблять нашу веб-програму більш схожою на рідну програму та забезпечують багатий досвід користувача.

Наприклад, великі компанії, такі як Twitter і Amazon, перетворили свої веб-додатки на PWA для більшого залучення користувачів.

Що таке PWA?

PWA = (веб-програма) + (деякі власні функції програми)

PWA — це ваш веб-додаток (HTML+CSS+JS). Він працює так само, як і ваша веб-програма, у всіх браузерах, як і раніше. Але він може мати власні функції, коли ваш веб-сайт завантажується в сучасному браузері. Це робить вашу веб-програму потужнішою, ніж раніше, а також робить її більш масштабованою, оскільки ми можемо попередньо завантажувати та кешувати активи у інтерфейсі, це зменшує запити до вашого серверного сервера.

Чим PWA відрізняється від Web App

  • Можливість встановлення: веб-програму можна встановити як рідну програму
  • Прогресивний: працює так само, як ваш веб-додаток, але з деякими власними функціями
  • Нативний досвід роботи з програмою: після встановлення користувач може використовувати веб-програму та переміщатися по ній як нативну.
  • Легкий доступ: на відміну від нашої веб-програми, нашим користувачам не потрібно вводити веб-адреси під час кожного відвідування. Після встановлення його можна відкрити одним дотиком.
  • Кешування додатків: до PWA єдиним механізмом кешування, який використовував наш веб-додаток, було використання кешу HTTP, який доступний лише для браузера. Але за допомогою PWA ми можемо кешувати речі, використовуючи сам код на стороні клієнта, який недоступний у веб-програмі.
  • Публікація в магазині (App/Play): PWA можна опублікувати в Google Play Store та IOS App Store.

Перетворення програми на PWA лише зробить її потужнішою.

Чому бізнесу варто розглянути PWA

Хоча більшість наших клієнтів звертаються до нас і просять спочатку розробити рішення для веб-додатків, а потім просять програми для Android та iOS. Все, що ми збираємося зробити, це створювати ту саму функціональність у веб-програмі для програми Android/IOS окремою командою, що потребує більших витрат на розробку та більше часу для виходу на ринок.

Але деякі клієнти мають обмежений бюджет або деякі клієнти можуть вважати, що час виходу на ринок є більш важливим для їх продукту.

Більшість вимог клієнта можуть бути задоволені самими функціями PWA. Для них ми пропонуємо лише PWA та пропонуємо їм перетворити свій PWA на додаток Android за допомогою TWA, якщо вони хочуть розгорнути його в Playstore.

Якщо вашій вимогі справді потрібні власні функції програми, які PWA не може задовольнити. Клієнти можуть піти та розробити обидві програми за своїм бажанням. Але навіть за такого сценарію. Вони можуть розгортати PWA в Play Store до завершення розробки Android.

Приклад: Titan Eyeplus

Спочатку вони розробили програму PWA та розгорнули її в Play Store за допомогою TWA (Trusted Web Activity). Після того, як вони завершили розробку додатків для Android. Вони розгорнули свою справжню програму для Android у Play Store. Вони досягли як часу виходу на ринок, використовуючи PWA, так і вартості розробки.

Функції PWA

PWA надає нашим веб-додаткам власні функції, подібні до програм.

Основні особливості:

  • Можливість інсталяції: веб-програма, встановлена ​​як рідна програма.
  • Кешування: можливе кешування програми, що забезпечує підтримку нашої програми в автономному режимі.
  • Push-сповіщення: Push-сповіщення можна надіслати з нашого сервера, щоб залучити наших користувачів до нашого веб-сайту.
  • Geofencing: програма може отримувати сповіщення про подію щоразу, коли змінюється місцезнаходження пристрою.
  • Запит на оплату: увімкніть оплату у своїй програмі з чудовим користуванням, як у рідній програмі.

І багато інших функцій, які з’являться в майбутньому.

Інші функції:

  • Ярлики: швидкодоступні URL-адреси, додані у файл маніфесту.
  • Web Share API: дозвольте вашій програмі отримувати спільні дані з інших програм.
  • Badge API: для відображення кількості сповіщень у встановленому PWA.
  • API періодичної фонової синхронізації: зберігає дані вашого користувача, доки його не буде підключено до мережі.
  • Вибір контактів: використовується для вибору контактів із мобільного телефону користувача.
  • Вибір файлу: використовується для доступу до файлу в локальній системі/мобільному пристрої
  Як виправити помилку призупиненого бездротового заряджання Samsung

Перевага PWA над рідною програмою

Рідна програма працює краще, ніж PWA, і має більше функцій, ніж PWA. Але все ж він має деякі переваги перед рідною програмою.

  • PWA працює на різних платформах, таких як Android, IOS, Desktop.
  • Це зменшує ваші витрати на розробку.
  • Просте розгортання функцій порівняно з рідною програмою.
  • Легко знайти, оскільки PWA (веб-сайт) є дружнім до SEO
  • Безпечний, оскільки працює лише на HTTPS

Недоліки PWA порівняно з рідною програмою

  • У порівнянні з нативною програмою доступні обмежені функції.
  • Функції PWA не гарантовано підтримують усі пристрої.
  • Бренд PWA низький, оскільки він недоступний у магазині додатків або магазині Play.

Ви можете розгорнути свій PWA як додаток для Android у Play Store за допомогою Android Довірена веб-активність (TWA). Це допоможе вашому бренду.

Речі, необхідні для перетворення Web App на PWA

Для перетворення будь-якої веб-програми або веб-сайту на PWA.

  • Service-Worker: ядро ​​будь-якої програми PWA для кешування, Push Notification, проксі для наших запитів.
  • Файл маніфесту: містить відомості про вашу веб-програму. Раніше він завантажував нашу програму як рідну програму на головному екрані.
  • Логотип програми: високоякісне зображення 512 x 512 пікселів для значка програми. Логотип додатка, потрібний для PWA на головному екрані, екрані-заставці тощо. Отже, ми маємо створити набір зображень із співвідношенням 1:1 для нашого APP за допомогою будь-яких інструментів.
  • Адаптивний дизайн: веб-програма має реагувати на роботу на екранах різних розмірів.

Що таке Service Worker:

Service Worker (сценарій на стороні клієнта) є проксі-сервером між вашою веб-програмою та зовнішньою стороною, доставляючи push-сповіщення для нашої веб-програми та підтримуючи кешування.

Service Worker працює незалежно від основного JavaScript. Тому він не має доступу до DOM API. Він може лише отримати доступ API IndexedDB, API Fetch, Cache Storage API. Але він може спілкуватися з основним потоком за допомогою повідомлення.

Послуги надаються сервісним працівником:

  • Перехоплення HTTP-запитів із вашого вихідного домену.
  • Отримувати Push-повідомлення від вашого сервера.
  • Офлайн доступність нашої програми

Сервіс-воркер контролює ваш додаток і може маніпулювати вашими запитами, але він працює незалежно. Тож з цієї причини вихідний домен має бути ввімкнено з HTTPS, щоб уникнути атаки «людина посередині».

Що таке файл маніфесту

Файл маніфесту (manifest.json) містить інформацію про нашу програму PWA, щоб повідомити браузеру.

  • name: Назва програми
  • short_name: Коротка назва нашої програми. Якщо передбачено
  • як із назвою властивості, так і з коротким_ім’ям, браузер візьме short_name.
  • description: Опис для опису нашої програми.
  • start_url: щоб указати домашню сторінку програми під час запуску нашого PWA.
  • значки: набір зображень для PWA для головного екрана тощо.
  • background_color: щоб встановити колір фону екрану-заставки в нашій програмі PWA.
  • дисплей: щоб налаштувати інтерфейс нашого браузера для відображення в нашій програмі PWA.
  • theme_color: колір теми програми PWA.
  • scope: область URL-адреси нашої програми для PWA. За замовчуванням використовується розташування файлу маніфесту.
  • ярлики: швидкі посилання для нашої програми PWA.

Перетворення веб-програми на PWA

Для демонстраційних цілей я створив структуру папок веб-сайту techukraine.net зі статичними файлами.

  • index.html – домашня сторінка
  • статті/
    • index.html – сторінка статей
  • автори/
    • index.html – сторінка авторів
  • інструменти/
    • index.html – сторінка інструментів
  • угоди/
    • index.html – сторінка угод

Якщо у вас уже є веб-сайт або веб-додаток, спробуйте перетворити його на PWA, виконавши наведені нижче дії.

Створіть необхідні зображення для PWA

По-перше, візьміть логотип своєї програми та обріжте його у співвідношенні 1:1 у 5 різних розмірах. Я використовував https://tools.crawlink.com/tools/pwa-icon-generator/ щоб швидко отримати зображення різних розмірів. Тож ви теж можете ним скористатися.

Створіть файл маніфесту

По-друге, створіть файл manifest.json для веб-програми з деталями вашої програми. Для демонстрації я створив файл маніфесту для веб-сайту techukraine.net.

{
	"name": "techukraine.net",
	"short_name": "techukraine.net",
	"description": "techukraine.net produces high-quality technology & finance articles, makes tools, and APIs to help businesses and people grow.",
	"start_url": "/",
	"icons": [{
		"src": "assets/icon/icon-128x128.png",
		"sizes": "128x128",
		"type": "image/png"
	}, {
		"src": "assets/icon/icon-152x152.png",
		"sizes": "152x152",
		"type": "image/png"
	}, {
		"src": "assets/icon/icon-192x192.png",
		"sizes": "192x192",
		"type": "image/png"
	}, {
		"src": "assets/icon/icon-384x384.png",
		"sizes": "384x384",
		"type": "image/png"
	}, {
		"src": "assets/icon/icon-512x512.png",
		"sizes": "512x512",
		"type": "image/png"
	}],
	"background_color": "#EDF2F4",
	"display": "standalone",
	"theme_color": "#B20422",
	"scope": "/",
	"shortcuts": [{
			"name": "Articles",
			"short_name": "Articles",
			"description": "1595 articles on Security, Sysadmin, Digital Marketing, Cloud Computing, Development, and many other topics.",
			"url": "https://geekflare.com/articles",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		},
		{
			"name": "Authors",
			"short_name": "Authors",
			"description": "techukraine.net - Authors",
			"url": "/authors",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		},
		{
			"name": "Tools",
			"short_name": "Tools",
			"description": "techukraine.net - Tools",
			"url": "https://techukraine.net.com/tools",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		},
		{
			"name": "Deals",
			"short_name": "Deals",
			"description": "techukraine.net - Deals",
			"url": "/deals",
			"icons": [{
				"src": "/assets/icon/icon-152x152.png",
				"sizes": "152x152"
			}]
		}
	]
}

Реєстрація Service-worker

створіть файл сценарію register-service-worker.js і service-worker.js у кореневій папці.

  Як автоматично додати завдання Microsoft Planner до календаря Outlook

Перший, register-service-worker.js — це файл javascript, який запускатиметься в основному потоці, який матиме доступ до DOM API. Але service-worker.js — це сценарій service worker, який працює незалежно від основного потоку, і його час життя також короткий. Він запускається щоразу, коли події викликають сервісних працівників і працюють до завершення процесу.

Перевіривши файл javascript основного потоку, ви можете перевірити, чи зареєстрований у ньому сервіс-воркер. якщо ні, ви можете зареєструвати сценарій Service Worker (service-worker.js).

вставте наведений нижче фрагмент у register-service-worker.js:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js');
    });
}

Вставте наведений нижче фрагмент у service-worker.js

self.addEventListener('install', (event) => { // event when service worker install
    console.log( 'install', event);
    self.skipWaiting();
});

self.addEventListener('activate', (event) => { // event when service worker activated
    console.log('activate', event);
    return self.clients.claim();
});

self.addEventListener('fetch', function(event) { // HTTP request interceptor
    event.respondWith(fetch(event.request)); // send all http request without any cache logic
    /*event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event. request);
        })
    );*/ // cache new request. if already in cache serves with the cache.
});

Ми не зосереджувалися на тому, як увімкнути кеш для офлайн-підтримки. Ми говоримо лише про те, як конвертувати веб-програми в PWA.

Додайте файл маніфесту та сценарій у тег all head вашої HTML-сторінки.

<link rel="manifest" href="https://techukraine.net.com/manifest.json">
<script src="/register-service-worker.js"></script>

Оновіть сторінку після додавання. Тепер ви можете встановити свою програму, як показано нижче, на мобільний хром.

На головному екрані програма додається.

Якщо ви використовуєте WordPress. Спробуйте використати існуючий плагін конвертера PWA. Для vueJS або reactJS ви можете скористатися наведеним вище методом або використати існуючі модулі PWA npm, щоб пришвидшити свою розробку. Оскільки модулі PWA npm уже ввімкнено з підтримкою офлайн-кешування тощо.

Увімкнути Push-сповіщення

Веб-повідомлення надсилаються в браузер, щоб наші користувачі частіше взаємодіяли з нашою програмою. Ми можемо ввімкнути це за допомогою

  • API сповіщень: використовується для налаштування того, як наше push-сповіщення має відображатися користувачеві.
  • Push API: використовується для отримання сповіщень, які надсилаються з нашого сервера до браузера.

Першим кроком, щоб увімкнути push-сповіщення в нашій програмі, є перевірка API сповіщень і отримання від користувача дозволу на показ сповіщень. Для цього скопіюйте та вставте наведений нижче фрагмент у свій register-service-worker.js.

if ('Notification' in window && Notification.permission != 'granted') {
    console.log('Ask user permission')
    Notification.requestPermission(status => {  
        console.log('Status:'+status)
        displayNotification('Notification Enabled');
    });
}


const displayNotification = notificationTitle => {
    console.log('display notification')
    if (Notification.permission == 'granted') {
        navigator.serviceWorker.getRegistration().then(reg => {
            console.log(reg)
            const options = {
                    body: 'Thanks for allowing push notification !',
                    icon:  '/assets/icons/icon-512x512.png',
                    vibrate: [100, 50, 100],
                    data: {
                      dateOfArrival: Date.now(),
                      primaryKey: 0
                    }
                  };
    
            reg.showNotification(notificationTitle, options);
        });
    }
};

Якщо все пройшло правильно. Ви отримаєте сповіщення від програми.

«Сповіщення» у вікні повідомить нам, що API сповіщень підтримується в цьому браузері. Notification.permission повідомить, що користувачеві дозволено показувати сповіщення. Якщо користувач дозволив нашу програму, значення буде «надано». якщо користувач відхилив, значення буде «заблоковано».

Увімкніть Firebase Cloud Messaging і створіть підписку

Тепер починається справжня частина. Для надсилання сповіщень із вашого сервера до користувача нам потрібна унікальна кінцева точка/підписка для кожного користувача. Для цього ми збираємося використовувати хмарний обмін повідомленнями firebase.

Як перший крок створіть обліковий запис Firebase, перейшовши за цим посиланням https://firebase.google.com/ і натисніть почати.

  • Створіть новий проект із назвою та натисніть «Продовжити». Я збираюся створити його з назвою techukraine.net.
  • На наступному кроці Google Analytics увімкнено за умовчанням. Ви можете перемкнути, що нам зараз це не потрібно, і натиснути «Продовжити». Ви можете ввімкнути його пізніше на консолі firebase, якщо вам потрібно.
  • Після створення проект виглядатиме, як показано нижче.
  •   Яка різниця між IPv4 та IPv6?

    Потім перейдіть до налаштувань проекту та натисніть хмарний обмін повідомленнями та згенеруйте ключі.

    З наведених вище кроків ви отримали 3 ключі.

    • ключ сервера проекту
    • Закритий ключ веб-сертифікатів push
    • Відкритий ключ веб-сертифікатів push

    Тепер вставте наведений нижче фрагмент у register-service-worker.js:

    const updateSubscriptionOnYourServer = subscription => {
        console.log('Write your ajax code here to save the user subscription in your DB', subscription);
        // write your own ajax request method using fetch, jquery, axios to save the subscription in your server for later use.
    };
    
    const subscribeUser = async () => {
        const swRegistration = await navigator.serviceWorker.getRegistration();
        const applicationServerPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; // paste your webpush certificate public key
        const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
        swRegistration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey
        })
        .then((subscription) => {
            console.log('User is subscribed newly:', subscription);
            updateSubscriptionOnServer(subscription);
        })
        .catch((err) => {
            if (Notification.permission === 'denied') {
              console.warn('Permission for notifications was denied')
            } else {
              console.error('Failed to subscribe the user: ', err)
            }
        });
    };
    const urlB64ToUint8Array = (base64String) => {
        const padding = '='.repeat((4 - base64String.length % 4) % 4)
        const base64 = (base64String + padding)
            .replace(/-/g, '+')
            .replace(/_/g, '/')
    
        const rawData = window.atob(base64);
        const outputArray = new Uint8Array(rawData.length);
    
        for (let i = 0; i < rawData.length; ++i) {
            outputArray[i] = rawData.charCodeAt(i);
        }
        return outputArray;
    };
    
    const checkSubscription = async () => {
        const swRegistration = await navigator.serviceWorker.getRegistration();
        swRegistration.pushManager.getSubscription()
        .then(subscription => {
            if (!!subscription) {
                console.log('User IS Already subscribed.');
                updateSubscriptionOnYourServer(subscription);
            } else {
                console.log('User is NOT subscribed. Subscribe user newly');
                subscribeUser();
            }
        });
    };
    
    checkSubscription();

    Вставте наведений нижче фрагмент у service-worker.js.

    self.addEventListener('push', (event) => {
      const json = JSON.parse(event.data.text())
      console.log('Push Data', event.data.text())
      self.registration.showNotification(json.header, json.options)
    });

    Тепер все налаштовано у передній частині. Використовуючи підписку, ви можете надсилати push-повідомлення своїм користувачам у будь-який час, поки їм не буде відмовлено в push-службах.

    Push із серверної частини node.js

    Ви можете використовувати web-push модуль npm, щоб зробити це простіше.

    Приклад фрагмента для надсилання push-сповіщень із сервера nodeJS.

    const webPush = require('web-push');
        // pushSubscription is nothing but subscription that you sent from your front-end to save it in DB
        const pushSubscription = {"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p256dh":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}};
        //your web certificates public-key
        const vapidPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY';
        //your web certificates private-key
        const vapidPrivateKey = 'web-certificate private key';
    
        var payload = JSON.stringify({
          "options": {
            "body": "PWA push notification testing fom backend",
            "badge": "/assets/icon/icon-152x152.png",
            "icon": "/assets/icon/icon-152x152.png",
            "vibrate": [100, 50, 100],
            "data": {
              "id": "458",
            },
            "actions": [{
              "action": "view",
              "title": "View"
            }, {
              "action": "close",
              "title": "Close"
            }]
          },
          "header": "Notification from techukraine.net-PWA Demo"
        });
    
        var options = {
          vapidDetails: {
            subject: 'mailto:[email protected]',
            publicKey: vapidPublicKey,
            privateKey: vapidPrivateKey
          },
          TTL: 60
        };
    
        webPush.sendNotification(
          pushSubscription,
          payload,
          options
        ).then(data => {
          return res.json({status : true, message : 'Notification sent'});
        }).catch(err => {
          return res.json({status : false, message : err });
        });

    Наведений вище код надішле push-сповіщення до підписки. Буде запущена подія push у service-worker.

    Push із серверної частини PHP

    Для серверної частини PHP ви можете використовувати web-push-php композитний пакет. Перегляньте приклад коду для надсилання push-повідомлень нижче.

    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    
    require __DIR__.'/../vendor/autoload.php';
    use MinishlinkWebPushWebPush;
    use MinishlinkWebPushSubscription;
    
    // subscription stored in DB
    $subsrciptionJson = '{"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p256dh":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}}';
    $payloadData = array (
    'options' =>  array (
                    'body' => 'PWA push notification testing fom backend',
                    'badge' => '/assets/icon/icon-152x152.png',
                    'icon' => '/assets/icon/icon-152x152.png',
                    'vibrate' => 
                    array (
                      0 => 100,
                      1 => 50,
                      2 => 100,
                    ),
                    'data' => 
                    array (
                      'id' => '458',
                    ),
                    'actions' => 
                    array (
                      0 => 
                      array (
                        'action' => 'view',
                        'title' => 'View',
                      ),
                      1 => 
                      array (
                        'action' => 'close',
                        'title' => 'Close',
                      ),
                    ),
    ),
    'header' => 'Notification from techukraine.net-PWA Demo',
    );
    
    // auth
    $auth = [
        'GCM' => 'your project private-key', // deprecated and optional, it's here only for compatibility reasons
        'VAPID' => [
            'subject' => 'mailto:[email protected]', // can be a mailto: or your website address
            'publicKey' => 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY', // (recommended) uncompressed public key P-256 encoded in Base64-URL
            'privateKey' => 'your web-certificate private-key', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
        ],
    ];
    
    $webPush = new WebPush($auth);
    
    $subsrciptionData = json_decode($subsrciptionJson,true);
    
    
    // webpush 6.0
    $webPush->sendOneNotification(
      Subscription::create($subsrciptionData),
      json_encode($payloadData) // optional (defaults null)
    );

    Висновок

    Сподіваюся, це дасть вам уявлення про перетворення веб-додатків на PWA. Ви можете перевірити вихідний код цієї статті тут і продемонструйте це тут. Я також перевірив push-сповіщення, надіславши його з серверної частини за допомогою прикладу коду.