У цій статті ми розглянемо процес трансформації звичайної веб-програми або сайту в PWA, використовуючи можливості Firebase Cloud Messaging для впровадження push-повідомлень.
Сьогодні багато веб-додатків трансформуються у прогресивні веб-додатки (PWA), оскільки вони надають низку цінних функцій, зокрема підтримку роботи в автономному режимі, push-повідомлення та фонову синхронізацію. Ці можливості роблять веб-програми більш схожими на нативні програми, забезпечуючи покращений користувацький досвід.
Прикладом успішного впровадження PWA є великі компанії, такі як Twitter та Amazon, які перетворили свої веб-ресурси на PWA для збільшення залучення користувачів.
Що таке PWA?
PWA поєднує в собі (веб-додаток) та (деякі нативні функції застосунків).
PWA по суті є вашим веб-додатком, створеним за допомогою HTML, CSS та JavaScript. Він функціонує як звичайний веб-сайт у будь-якому браузері, але здатний розширювати свої можливості при завантаженні в сучасному браузері. Це робить веб-програму потужнішою та масштабованішою, оскільки дозволяє попередньо завантажувати та кешувати ресурси на інтерфейсі, що зменшує кількість запитів до сервера.
Відмінності між PWA і традиційним веб-додатком
- Можливість встановлення: PWA можна встановити на пристрій як нативну програму.
- Прогресивність: працює як звичайний веб-додаток, але з розширеними функціями.
- Нативний досвід: після встановлення користувач взаємодіє з PWA так само, як і з нативною програмою.
- Простий доступ: на відміну від веб-додатків, користувачам не потрібно вводити URL-адресу кожного разу. Після встановлення PWA відкривається одним дотиком.
- Розширене кешування: PWA використовує можливості кешування на стороні клієнта, окрім HTTP-кешу браузера.
- Публікація в магазинах: PWA можна розміщувати в Google Play Store та iOS App Store.
Трансформація вашого веб-додатка в PWA значно розширює його можливості.
Чому PWA важливі для бізнесу?
Традиційно розробка починається з веб-додатків, а потім створюються окремі додатки для Android та iOS. Це означає повторення функціональності та збільшення витрат і часу на розробку.
Однак деякі клієнти мають обмежений бюджет або час виходу на ринок є критичним фактором.
Багато потреб клієнтів можуть бути задоволені можливостями PWA. Ми пропонуємо клієнтам PWA та їхню трансформацію в додаток Android через TWA (Trusted Web Activity) для розміщення в Play Store.
Якщо потрібні унікальні нативні функції, які PWA не може надати, клієнт може розробляти обидва типи додатків. Але навіть у цьому випадку можна запустити PWA в Play Store до завершення розробки нативного додатка.
Приклад: Titan Eyeplus
Спочатку компанія розробила PWA, який розмістила в Play Store через TWA. Після завершення розробки нативного додатку для Android, його також було опубліковано. Це дозволило Titan Eyeplus досягти швидкого виходу на ринок та оптимізувати витрати на розробку.
Функціональні можливості PWA
PWA наділяє веб-додатки функціями, які є характерними для нативних програм.
Основні можливості:
- Встановлення: можливість встановлення веб-додатку як нативної програми.
- Кешування: можливість кешувати дані для забезпечення роботи додатку в автономному режимі.
- Push-повідомлення: можливість надсилати push-повідомлення з сервера для залучення користувачів.
- Геозонування: можливість отримання сповіщень при зміні місцезнаходження пристрою.
- Платіжні запити: можливість впровадження платіжних рішень з покращеним користувацьким досвідом.
І багато інших функцій, які з’являться в майбутньому.
Додаткові можливості:
- Ярлики: швидкий доступ до важливих розділів сайту.
- Web Share API: обмін даними з іншими додатками.
- Badge API: індикація кількості сповіщень на значку PWA.
- API періодичної фонової синхронізації: збереження даних користувача до відновлення мережі.
- Вибір контактів: доступ до контактів на пристрої.
- Вибір файлів: доступ до файлів у локальній системі/мобільному пристрої.
Переваги PWA над нативними додатками
Хоча нативні додатки часто забезпечують кращу продуктивність та ширші функціональні можливості, PWA мають свої переваги:
- Кросплатформність: PWA працюють на Android, iOS, Desktop.
- Зниження витрат: Розробка PWA зазвичай є дешевшою.
- Простота оновлень: Оновлення PWA є набагато простішими.
- Пошукова оптимізація: PWA (як веб-сайти) є дружніми до SEO.
- Безпека: PWA працюють тільки через HTTPS.
Недоліки PWA порівняно з нативними додатками
- Обмежена функціональність: PWA можуть не мати доступу до всіх апаратних та програмних можливостей пристрою.
- Обмеження підтримки: Функціонал PWA не гарантовано підтримується на всіх пристроях.
- Слабка ідентифікація: PWA не представлені в магазинах додатків, що може знижувати довіру користувачів.
Завдяки інструменту Android Trusted Web Activity (TWA), PWA можна публікувати в Play Store, що покращує їх впізнаваність.
Необхідні компоненти для конвертації веб-додатку в PWA
Для перетворення будь-якого веб-додатку або веб-сайту в PWA, вам знадобляться:
- Service Worker: ключовий елемент PWA для кешування, push-повідомлень, обробки запитів.
- Файл маніфесту: містить метадані вашого веб-додатку, необхідні для встановлення на головний екран.
- Логотип програми: високоякісне зображення (512 x 512 пікселів), необхідне для значка PWA.
- Адаптивний дизайн: веб-додаток має коректно відображатися на екранах різних розмірів.
Що таке Service Worker?
Service Worker – це скрипт на стороні клієнта, що працює як проксі-сервер між вашою веб-програмою та мережею, обробляючи push-повідомлення та керуючи кешуванням.
Service Worker працює незалежно від основного JavaScript, тому не має доступу до DOM API. Він може використовувати IndexedDB API, Fetch API, Cache Storage API. Зв’язок з основним потоком здійснюється через обмін повідомленнями.
Функції, які забезпечує Service Worker:
- Перехоплення HTTP-запитів з вашого домену.
- Отримання push-повідомлень з сервера.
- Забезпечення автономної роботи додатка.
Service Worker контролює ваш додаток та може маніпулювати запитами, але працює незалежно, тому домен має підтримувати HTTPS для захисту від атак “людина посередині”.
Що таке файл маніфесту?
Файл маніфесту (manifest.json) містить інформацію про ваш PWA, необхідну для браузера:
- name: Назва програми.
- short_name: Скорочена назва (якщо задана, браузер використовуватиме саме її).
- description: Опис програми.
- start_url: URL-адреса головної сторінки PWA.
- icons: Набір зображень для PWA.
- background_color: Колір фону екрана завантаження PWA.
- display: Спосіб відображення PWA у браузері.
- theme_color: Колір теми PWA.
- scope: Область URL-адрес, на які поширюється PWA (за замовчуванням – розташування файлу маніфесту).
- shortcuts: Швидкий доступ до окремих розділів PWA.
Конвертація веб-програми в PWA
Для демонстрації процесу, візьмемо за приклад структуру папок сайту techukraine.net зі статичними файлами.
- index.html – Головна сторінка
- статті/
- index.html – сторінка статей
- автори/
- index.html – сторінка авторів
- інструменти/
- index.html – сторінка інструментів
- угоди/
- index.html – сторінка угод
Якщо у вас вже є веб-сайт або веб-додаток, спробуйте конвертувати його в PWA, слідуючи цим інструкціям.
Створення необхідних зображень для PWA
Спочатку підготуйте логотип вашої програми, обрізавши його до співвідношення сторін 1:1 у п’яти різних розмірах. Для швидкого створення необхідних зображень можна використовувати онлайн-інструмент, наприклад 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 у кореневій папці.
Файл register-service-worker.js буде виконуватися в головному потоці та матиме доступ до DOM API, а service-worker.js — це скрипт сервісного працівника, що виконується незалежно від основного потоку. Він запускається, коли виникають події, що стосуються сервісного працівника, і продовжує працювати до завершення процесу.
У файлі javascript основного потоку перевірте, чи зареєстрований сервіс-воркер. Якщо ні, зареєструйте скрипт сервісного працівника (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.
Додайте файл маніфесту та скрипт до тегу <head> вашої HTML-сторінки.
<link rel="manifest" href="https://techukraine.net.com/manifest.json"> <script src="/register-service-worker.js"></script>
Після додавання оновіть сторінку. Тепер ви можете встановити вашу програму, як показано нижче, у мобільному браузері Chrome.
Після встановлення додаток з’явиться на головному екрані.
Якщо ви використовуєте WordPress, спробуйте скористатися плагіном для конвертації в PWA. Для vueJS або reactJS, ви можете застосувати описаний вище метод або скористатися готовими модулями PWA npm для прискорення розробки. Модулі PWA npm вже мають підтримку офлайн-кешування та інших функцій.
Увімкнення Push-повідомлень
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); }); } };
Якщо все зроблено правильно, ви отримаєте сповіщення від програми.
Об’єкт “Notification” у вікні вказує на підтримку API сповіщень у даному браузері. Notification.permission повідомляє про надання дозволу на показ сповіщень. Якщо користувач дозволив показ сповіщень, значення буде “granted”, інакше – “denied”.
Увімкнення Firebase Cloud Messaging та створення підписки
Для надсилання повідомлень з сервера користувачу потрібна унікальна кінцева точка/підписка. Для цього ми будемо використовувати Firebase Cloud Messaging.
Першим кроком створіть обліковий запис Firebase за посиланням https://firebase.google.com/ та натисніть «Почати».
- Створіть новий проект з назвою та натисніть «Продовжити». Ми створимо його з назвою techukraine.net.
- На наступному кроці Google Analytics буде увімкнено за замовчуванням. Ви можете перемкнути, що нам зараз це не потрібно, і натиснути «Продовжити». Ви можете ввімкнути його пізніше на консолі Firebase.
- Після створення проект виглядатиме, як показано нижче.
Далі перейдіть до налаштувань проекту, натисніть “Хмарний обмін повідомленнями” та згенеруйте ключі.
У результаті цих дій ви отримаєте 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) });
На цьому налаштування front-end завершено. Використовуючи підписку, ви можете надсилати push-повідомлення користувачам, доки їх не буде відхилено.
Надсилання Push-повідомлень з Node.js
Для спрощення цієї задачі ви можете скористатися модулем npm web-push.
Ось приклад фрагменту коду для надсилання 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. Вихідний код статті доступний тут, а демонстрація – <a href=”https://aghilanbaskar.github.io/pwa-demo