如何使用推送通知将 WebApp 转换为 PWA
已发表: 2022-03-20在本文中,我们将了解如何使用 Firebase 云消息传递将 Web 应用程序或网站转换为带有推送通知的 PWA。
在现代世界中,大多数 Web 应用程序正在转换为 PWA(渐进式 Web 应用程序),因为它提供了离线支持、推送通知、后台同步等功能。 PWA 功能使我们的 Web 应用程序更像原生应用程序,并提供丰富的用户体验。
例如,像 Twitter 和亚马逊这样的大公司已经将他们的 Web 应用程序转换为 PWA 以提高用户参与度。
什么是 PWA?
PWA = (Web App) + (一些原生应用功能)
PWA 是您的同一个 Web 应用程序(HTML+CSS+JS)。 它在所有浏览器上的工作方式与您的 Web 应用程序相同,就像以前一样。 但是当您的网站在现代浏览器上加载时,它可以具有本机功能。 它使您的 Web 应用程序比以前更强大,也使其更具可扩展性,因为我们可以在前端预取和缓存资产,它减少了对后端服务器的请求。
PWA 与 Web App 有何不同
- 可安装:您的 Web 应用可以像原生应用一样安装
- 渐进式:与您的网络应用程序相同,但具有一些本机功能
- 原生应用体验:一旦安装,用户就可以像原生应用一样使用和导航 Web 应用。
- 易于访问:与我们的网络应用程序不同,我们的用户无需在每次访问时都输入网址。 安装后,只需轻轻一按即可打开。
- 应用程序缓存:在 PWA 之前,我们的 Web 应用程序实现的唯一缓存机制是使用仅对浏览器可用的 HTTP 缓存。 但是使用 PWA,我们可以使用 Web 应用程序中不可用的客户端代码本身来缓存内容。
- (App/Play) 商店发布: PWA 可以在 Google Play Store 和 IOS App Store 发布。
将您的应用程序转换为 PWA 只会使其更强大。
为什么企业应该考虑 PWA
虽然我们的大多数客户联系我们并要求首先开发 Web App 解决方案,然后他们要求 Android 和 iOS 应用程序。 我们要做的就是由一个单独的团队在 web 应用程序中构建与 Android/IOS 应用程序相同的功能,这需要更多的开发成本和更多的上市时间。
但是有些客户的预算有限,或者有些客户可能认为上市时间对他们的产品更重要。
PWA 功能本身可以满足大多数客户端需求。 对于他们,我们只建议 PWA,如果他们想在 Playstore 中部署,我们建议他们使用 TWA 将他们的 PWA 转换为 Android 应用程序。
如果您的需求确实需要 PWA 无法满足的原生应用程序功能。 客户可以按照自己的意愿去开发这两个应用程序。 但即使在那种情况下。 他们可以在 Play 商店中部署 PWA,直到 Android 开发完成。
示例:泰坦 Eyeplus
最初,他们开发了一个 PWA 应用程序,并使用 TWA(Trusted Web Activity)将其部署在 Play 商店中。 一旦他们完成了他们的 Android 应用程序开发。 他们在 Play 商店中部署了他们真正的 Android 应用程序。 他们使用 PWA 实现了上市时间和开发成本。
PWA 功能
PWA 为我们的 Web 应用程序提供了类似原生应用程序的功能。
主要特点是:
- 可安装:像本机应用程序一样安装的 Web 应用程序。
- 缓存:应用程序缓存是可能的,这为我们的应用程序提供了离线支持。
- 推送通知:可以从我们的服务器发送推送通知,以吸引我们的用户访问我们的网站。
- 地理围栏:只要设备位置发生变化,就可以通过事件通知应用程序。
- 支付请求:在您的应用程序中启用支付功能,并像原生应用程序一样提供出色的用户体验。
未来还有更多功能。
其他特点是:
- 快捷方式:清单文件中添加的可快速访问的 URL。
- Web Share API:让您的应用程序接收来自其他应用程序的共享数据。
- 徽章 API:在已安装的 PWA 中显示通知计数。
- 定期后台同步 API:保存用户的数据,直到它连接到网络。
- 联系人选择器:用于从用户的手机中选择联系人。
- 文件选择器:用于访问本地系统/移动设备上的文件
PWA 相对于原生应用程序的优势
本机应用程序比 PWA 性能更好,并且比 PWA 具有更多功能。 但是,它仍然比本机应用程序具有一些优势。
- PWA 在 Android、IOS、桌面等跨平台上运行。
- 它降低了您的开发成本。
- 与本机应用程序相比,易于功能部署。
- 易于发现,因为 PWA(网站)对 SEO 友好
- 安全,因为它仅适用于 HTTPS
PWA 相对于原生应用程序的缺点
- 与本机应用程序相比,可用的功能有限。
- PWA 功能不保证支持所有设备。
- PWA 的品牌知名度很低,因为它在应用商店或 Play 商店中不可用。
您可以使用 android Trusted Web Activity (TWA) 在 Play 商店中将 PWA 部署为 Android 应用程序。 这将有助于您的品牌推广。
将 Web App 转换为 PWA 所需的东西
用于将任何 Web 应用程序或网站转换为 PWA。
- Service-Worker:任何用于缓存、推送通知的 PWA 应用程序的核心,是我们请求的代理。
- 清单文件:它包含有关您的 Web 应用程序的详细信息。 它曾经像在主屏幕上下载我们的应用程序一样下载我们的应用程序。
- 应用程序徽标:应用程序图标的高质量图像 512 x 512 像素。 PWA 在主屏幕、启动屏幕等上需要应用徽标。因此我们必须使用任何工具为我们的 APP 创建一组 1:1 比例的图像。
- 响应式设计:Web 应用程序应该能够响应不同屏幕尺寸的工作。
什么是服务工作者:
服务工作者(客户端脚本)是您的 Web 应用程序和外部之间的代理,为我们的 Web 应用程序提供推送通知并支持缓存。
Service Worker 独立于主 javascript 运行。 所以它无法访问 DOM API。 它只能访问 IndexedDB API、Fetch API、Cache Storage API。 但它可以通过消息与主线程通信。
service worker 提供的服务:
- 拦截来自您的源域的 HTTP 请求。
- 从您的服务器接收推送通知。
- 我们的应用程序的离线可用性
Service Worker 控制您的应用程序并可以操纵您的请求,但它独立运行。 因此,出于这个原因,必须使用 HTTPS 启用源域以避免中间人攻击。
什么是清单文件
清单文件 (manifest.json) 包含有关我们的 PWA 应用程序的详细信息,以告知浏览器。
- 名称:应用程序的名称
- short_name:我们的应用程序的简称。 如果提供
- 同时具有属性名称和短名称,浏览器将采用短名称。
- 描述:描述我们的应用程序的描述。
- start_url:指定我们的 PWA 启动时应用程序的主页。
- 图标:用于主屏幕等的 PWA 图像集。
- background_color:在我们的 PWA 应用程序中设置启动画面的背景颜色。
- display:自定义我们的浏览器 UI 以显示在我们的 PWA 应用程序中。
- theme_color:PWA 应用的主题颜色。
- 范围:我们为 PWA 考虑的应用程序的 URL 范围。 默认为清单文件所在的位置。
- 快捷方式:我们的 PWA 应用程序的快速链接。
将 Web 应用程序转换为 PWA
出于演示目的,我创建了一个带有静态文件的 Geekflare 网站文件夹结构。
- index.html – 主页
- 文章/
- index.html – 文章页面
- 作者/
- index.html – 作者页面
- 工具/
- index.html – 工具页面
- 交易/
- index.html – 交易页面
如果您已经有任何网站或 Web 应用程序,请尝试按照以下步骤将其转换为 PWA。
为 PWA 创建所需的图像
首先,获取您的应用程序徽标,并以 1:1 的比例将其裁剪为 5 种不同的尺寸。 我已经使用 https://tools.crawlink.com/tools/pwa-icon-generator/ 快速获得不同的图像尺寸。 所以你也可以使用它。
创建清单文件
其次,使用您的应用程序详细信息为您的 Web 应用程序创建一个 manifest.json 文件。 对于演示,我为 Geekflare 网站创建了一个清单文件。
{ “名称”:“Geekflare”, "short_name": "Geekflare", "description": "Geekflare 制作高质量的技术和金融文章,制作工具和 API 来帮助企业和人们成长。", "start_url": "/", “图标”:[{ "src": "assets/icon/icon-128x128.png", “尺寸”:“128x128”, “类型”:“图像/png” }, { "src": "assets/icon/icon-152x152.png", “尺寸”:“152x152”, “类型”:“图像/png” }, { "src": "assets/icon/icon-192x192.png", “尺寸”:“192x192”, “类型”:“图像/png” }, { "src": "assets/icon/icon-384x384.png", “尺寸”:“384x384”, “类型”:“图像/png” }, { "src": "assets/icon/icon-512x512.png", “尺寸”:“512x512”, “类型”:“图像/png” }], "background_color": "#EDF2F4", “显示”:“独立”, "theme_color": "#B20422", “范围”: ”/”, “捷径”:[{ “名称”:“文章”, "short_name": "文章", "description": "1595 篇关于安全、系统管理员、数字营销、云计算、开发和许多其他主题的文章。", “网址”:“/文章”, “图标”:[{ "src": "/assets/icon/icon-152x152.png", “尺寸”:“152x152” }] }, { “名称”:“作者”, "short_name": "作者", "description": "Geekflare - 作者", “网址”:“/作者”, “图标”:[{ "src": "/assets/icon/icon-152x152.png", “尺寸”:“152x152” }] }, { “名称”:“工具”, "short_name": "工具", "description": "Geekflare - 工具", “网址”:“/工具”, “图标”:[{ "src": "/assets/icon/icon-152x152.png", “尺寸”:“152x152” }] }, { “名称”:“交易”, "short_name": "交易", "description": "Geekflare - 优惠", “网址”:“/交易”, “图标”:[{ "src": "/assets/icon/icon-152x152.png", “尺寸”:“152x152” }] } ] }
注册服务工作者
在根文件夹中创建脚本文件 register-service-worker.js 和 service-worker.js。
第一个,register-service-worker.js 是 javascript 文件,将在可以访问 DOM API 的主线程上运行。 但是 service-worker.js 是一个独立于主线程运行的 service worker 脚本,它的生命周期也很短。 每当事件调用服务工作者时它就会运行并运行直到它完成该过程。
通过检查主线程 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) => { // service worker 安装时的事件 console.log('安装',事件); self.skipWaiting(); }); self.addEventListener('activate', (event) => { // service worker 激活时的事件 console.log('激活',事件); 返回 self.clients.claim(); }); self.addEventListener('fetch', function(event) { // HTTP 请求拦截器 event.respondWith(fetch(event.request)); // 发送所有 http 请求,没有任何缓存逻辑 /*event.respondWith( caches.match(event.request).then(function(response) { 返回响应 || 获取(事件。请求); }) );*/ // 缓存新请求。 如果已经在缓存中,则与缓存一起使用。 });
我们没有专注于如何启用缓存以支持离线支持。 我们只讨论如何将 Web 应用程序转换为 PWA。
在 HTML 页面的 all head 标签中添加清单文件和脚本。
<link rel="manifest" href="/manifest.json"> <script src="/register-service-worker.js"></script>
添加后刷新页面。 现在您可以在移动 chrome 上安装您的应用程序,如下所示。

在主屏幕上,应用程序被添加。

如果您使用的是 WordPress。 尝试使用现有的 PWA 转换器插件。 对于 vueJS 或 reactJS,您可以按照上述方法或使用现有的 PWA npm 模块来加快您的开发速度。 因为 PWA npm 模块已经启用了离线支持缓存等。
启用推送通知
Web 推送通知被发送到浏览器,以使我们的用户更频繁地与我们的应用程序互动/互动。 我们可以通过使用启用它
- Notification API:用于配置我们的推送通知应该如何显示给用户。
- Push API:用于接收从我们的服务器发送到浏览器的通知消息。
在我们的应用程序中启用推送通知的第一步是检查通知 API 并从用户那里获得显示通知的权限。 对于该复制并将下面的代码段粘贴到您的 register-service-worker.js 中。
if ('Notification' in window && Notification.permission != 'granted') { console.log('询问用户权限') Notification.requestPermission(状态 => { console.log('状态:'+状态) displayNotification('通知已启用'); }); } 常量 displayNotification = notificationTitle => { console.log('显示通知') if (Notification.permission == 'granted') { navigator.serviceWorker.getRegistration().then(reg => { 控制台日志(注册) 常量选项 = { body: '感谢允许推送通知!', 图标:'/assets/icons/icon-512x512.png', 振动:[100, 50, 100], 数据: { dateOfArrival: Date.now(), 主键:0 } }; reg.showNotification(通知标题,选项); }); } };
如果一切顺利。 您将收到来自应用程序的通知。



窗口中的“通知”将告诉我们该浏览器支持通知 API。 Notification.permission将告诉用户已被允许显示通知。 如果用户允许我们的应用程序,则该值将被“授予”。 如果用户拒绝了该值,则该值将被“阻止”。
启用 Firebase 云消息传递并创建订阅
现在真正的部分开始了。 为了从您的服务器向用户推送通知,我们需要为每个用户提供一个唯一的端点/订阅。 为此,我们将使用 firebase 云消息传递。
第一步,通过访问此链接 https://firebase.google.com/ 创建一个 Firebase 帐户,然后按开始。
- 使用名称创建一个新项目,然后按继续。 我将使用名称 Geekflare 创建它。
- 在下一步中,默认情况下启用 Google Analytics。 您可以切换我们现在不需要它,然后按继续。 如果需要,您可以稍后在 Firebase 控制台中启用它。
- 创建项目后,它将如下所示。

然后转到项目设置并单击云消息传递并生成密钥。

通过上述步骤,您获得了 3 个密钥。
- 项目服务器密钥
- Web 推送证书私钥
- 网络推送证书公钥
现在将以下代码段粘贴到 register-service-worker.js 中:
常量 updateSubscriptionOnYourServer = 订阅 => { console.log('在此处编写您的 ajax 代码以将用户订阅保存在您的数据库中', subscription); // 使用 fetch、jquery、axios 编写自己的 ajax 请求方法,将订阅保存在服务器中以备后用。 }; const subscribeUser = async () => { const swRegistration = 等待 navigator.serviceWorker.getRegistration(); 常量 applicationServerPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; // 粘贴你的 webpush 证书公钥 常量 applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey); swRegistration.pushManager.subscribe({ userVisibleOnly:真, 应用服务器密钥 }) .then((订阅) => { console.log('用户新订阅:', subscription); updateSubscriptionOnServer(订阅); }) .catch((错误) => { if (Notification.permission === '拒绝') { console.warn('通知权限被拒绝') } 别的 { console.error('订阅用户失败:', err) } }); }; 常量 urlB64ToUint8Array = (base64String) => { const padding = '='.repeat((4 - base64String.length % 4) % 4) const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/') 常量 rawData = window.atob(base64); 常量 outputArray = new Uint8Array(rawData.length); for (让 i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } 返回输出数组; }; const checkSubscription = async () => { const swRegistration = 等待 navigator.serviceWorker.getRegistration(); swRegistration.pushManager.getSubscription() .then(订阅 => { 如果(!!订阅){ console.log('用户已订阅'); updateSubscriptionOnYourServer(订阅); } 别的 { console.log('用户未订阅。新订阅用户'); 订阅用户(); } }); }; 检查订阅();
将以下代码段粘贴到 service-worker.js 中。
self.addEventListener('push', (event) => { 常量 json = JSON.parse(event.data.text()) console.log('推送数据', event.data.text()) self.registration.showNotification(json.header, json.options) });
现在全部设置在前端。 通过使用订阅,您可以随时向您的用户发送推送通知,直到他们没有被拒绝推送服务。
从 node.js 后端推送
您可以使用 web-push npm 模块使其更容易。
从 nodeJS 服务器发送推送通知的示例片段。
常量 webPush = 要求('web-push'); // pushSubscription 只不过是您从前端发送的订阅以将其保存在数据库中 const pushSubscription = {"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2…E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8w","p2 :"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}}; //你的网络证书公钥 常量 vapidPublicKey = 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY'; //你的网络证书私钥 const vapidPrivateKey = '网络证书私钥'; var 有效负载 = JSON.stringify({ “选项”: { "body": "后端 PWA 推送通知测试", "徽章": "/assets/icon/icon-152x152.png", "icon": "/assets/icon/icon-152x152.png", “振动”:[100, 50, 100], “数据”: { “id”:“458”, }, “行动”:[{ “动作”:“视图”, “标题”:“视图” }, { “动作”:“关闭”, “标题”:“关闭” }] }, "header": "来自 Geekflare-PWA 演示的通知" }); 变量选项 = { 虚无细节:{ 主题:'mailto:[电子邮件保护]', 公钥:vapidPublicKey, 私钥:vapidPrivateKey }, 生存时间:60 }; webPush.sendNotification( 推送订阅, 有效载荷, 选项 ).then(数据 => { return res.json({status : true, message : '通知发送'}); }).catch(错误 => { 返回 res.json({status : false, message : err }); });
上面的代码将向订阅发送推送通知。 service-worker 中的推送事件将被触发。
从 PHP 后端推送
对于 PHP 后端,您可以使用 web-push-php 作曲家包。 检查示例代码以发送下面的推送通知。
<?php if ( !defined('BASEPATH')) exit('不允许直接脚本访问'); 需要 __DIR__.'/../vendor/autoload.php'; 使用 Minishlink\WebPush\WebPush; 使用 Minishlink\WebPush\Subscription; // 订阅存储在数据库中 $subsrciptionJson = '{"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABh2...E0mTFsHtUqaye8UCoLBq8sHCgo2IC7UaafhjGmVCG_SCdhZ9Z88uGj-uwMcg","keys":{"auth":"qX6AMD5JWbu41cFWE3Lk8"p526dh8 ":"BLxHw0IMtBMzOHnXgPxxMgSYXxwzJPxpgR8KmAbMMe1-eOudcIcUTVw0QvrC5gWOhZs-yzDa4yKooqSnM3rnx7Y"}}'; $payloadData = 数组 ( '选项' => 数组 ( 'body' => '后端的 PWA 推送通知测试', '徽章' => '/assets/icon/icon-152x152.png', '图标' => '/assets/icon/icon-152x152.png', '振动' => 大批 ( 0 => 100, 1 => 50, 2 => 100, ), '数据' => 大批 ( 'id' => '458', ), '行动' => 大批 ( 0 => 大批 ( '动作' => '视图', '标题' => '视图', ), 1 => 大批 ( '动作' => '关闭', '标题' => '关闭', ), ), ), 'header' => '来自 Geekflare-PWA Demo 的通知', ); // 认证 $身份验证 = [ 'GCM' => 'your project private-key', // 已弃用且可选,此处仅出于兼容性原因 'VAPID' => [ 'subject' => 'mailto:[email protected]', // 可以是 mailto: 或您的网站地址 'publicKey' => 'BOcTIipY07N4Y63Y-9r7NMoJHofmCzn3Pu9g-LMsgIMGH4HVr42_LW9ia0lMr68TsTLKS3UcdkE3IcC52hJDYsY', //(推荐)以 Base64-URL 编码的未压缩公钥 P-256 'privateKey' => 'your web-certificate private-key', //(推荐)实际上是 Base64-URL 中编码的私钥的秘密乘数 ], ]; $webPush = 新的 WebPush($auth); $subsrciptionData = json_decode($subsrciptionJson,true); // 网络推送 6.0 $webPush->sendOneNotification( 订阅::create($subsrciptionData), json_encode($payloadData) // 可选(默认为空) );
结论
我希望这能让您对将 Web 应用程序转换为 PWA 有所了解。 您可以在此处查看本文的源代码并在此处进行演示。 我也在示例代码的帮助下通过从后端发送推送通知来测试推送通知。