背景
这几天比较闲,又在闭门造轮子,这次在做一个即时通讯 WebApp。前后端交互用WebSocket完成。现代浏览器的各种新特性支持(做点东西自己玩,不需要考虑向前兼容),也使打造一个跨平台的 WebApp 更加轻松。
作为一个即时通讯应用,后台的消息推送是很有必要的。原生应用实现这个比较轻松,各个平台都有提供推送服务,再不济后台保持一个长连接,或是定时轮询,这都是可行的。
然而 WebApp 无法保持一个长连接或者是持续轮询,因为我们期望的是在桌面端关闭标签页后(不关闭浏览器),或是在移动端是将浏览器放在后台之后,WebApp 能够继续监听推送并通知,它并不能驻留后台。就算是Service Worker仍无法做到这点,因为它只能由事件唤醒后,运行一小段时间后被浏览器停止。
PWA 时代的推送通道:Push API
当然了PWA的好时代还是提供了接受推送的特性,这便是Push API。
它可以让 Web 服务器推送通知给Push Service,然后由后者转发给用户代理(即用户的浏览器),再接下来Service Worker被 push 事件唤醒,通过Notification API给用户发一条通知,推送就算完了。
这里先说明,Push API无法脱离Notification API存在,相反则是可以的。如果没有后者,推送事件就无法反馈给用户;因为在页面关闭,只有Service Worker被唤醒的情况下,没有前端界面,通知是与用户交流的唯一渠道。(这是伏笔)
缺点
看到上面的特性,我是十分动心的。可惜 PWA 终究不是原生应用,至少现在不是。美梦将醒。
Push Service 无法访问
最严重的问题。我们伟大的某虚拟混凝土建筑物阻挡了 FCM (Firebase Cloud Messaging),Google 的 Push Service 。因此它的推送前往用户端的路途就被阻断。虽然不是技术本身的问题,但是它占有推送服务的大部分,安卓的移动端大部分浏览器都使用 FCM 作为推送服务。在有梯子的情况下没有问题,但是这大大降低了可用性。
浏览器并非完全支持
标题重点批评 Android 与 Windows 上的Firefox。它使用自家的推送服务(未被屏蔽),在控制台输出一切正常,有推送。但是Notification API完全不可用。
我尝试了 registration.showNotification (在事件内调用) 和 new Notification() ,均无法使用。上文也说了,没有通知的Push API是没有意义的。所以,这算是彻底断了后路了。
使用 Simple Push Demo (一个开源项目)可以很方便地获知浏览器使用的推送服务,和调试其是否正常。以下是各平台我的测试结果:
- Windows ,
Chrome在梯子下表现正常;Firefox使用自家推送服务,推送正常、通知不正常。 - Android ,
ChromeEdgeOperaVivaldi在梯子下表现正常。话说微软明明自己有推送服务啊,不过前面四个用的都是 FCM 。Firefox与 Windows 下的表现相同。 - Linux (Kali) ,
Firefox ESR使用自家推送服务,推送正常,通知正常。 - iOS ,抱歉手头没设备。不过我猜测强制使用苹果的推送服务 APNs 。至少国内可以访问,而且通知大概是正常的,闭源生态优势我是享受不到了。
结言
见证如此不完善的新特性(其实早已实现),有点失望,不过也能理解。期待能见证 Web 生态越发完善,不仅仅是隐藏地址栏那么简单,而且集成了强大且跨平台的 API。不仅在体验上无限接近原生应用,也要在各方面有超越原生应用的特性。跨平台是大多 Web 技术的共性,我希望它的开发也应该尽量简单,这与功能强大并不冲突。
其实以后在网页中运行大型游戏也有可能......我对这个十分外行,不过我知道WebGL和WebAssembly,也许 Web 应用的性能真的会飞升。
期望一个更开放,更统一的 Web 世界。
(明明是抱怨问题,我是如何把主题升华到这个程度的)