背景

这几天比较闲,又在闭门造轮子,这次在做一个即时通讯 WebApp。前后端交互用WebSocket完成。现代浏览器的各种新特性支持(做点东西自己玩,不需要考虑向前兼容),也使打造一个跨平台的 WebApp 更加轻松。

作为一个即时通讯应用,后台的消息推送是很有必要的。原生应用实现这个比较轻松,各个平台都有提供推送服务,再不济后台保持一个长连接,或是定时轮询,这都是可行的。

然而 WebApp 无法保持一个长连接或者是持续轮询,因为我们期望的是在桌面端关闭标签页后(不关闭浏览器),或是在移动端是将浏览器放在后台之后,WebApp 能够继续监听推送并通知,它并不能驻留后台。就算是Service Worker仍无法做到这点,因为它只能由事件唤醒后,运行一小段时间后被浏览器停止。

PWA 时代的推送通道:Push API

当然了PWA的好时代还是提供了接受推送的特性,这便是Push API。 它可以让 Web 服务器推送通知给Push Service,然后由后者转发给用户代理(即用户的浏览器),再接下来Service Workerpush 事件唤醒,通过Notification API给用户发一条通知,推送就算完了。

这里先说明,Push API无法脱离Notification API存在,相反则是可以的。如果没有后者,推送事件就无法反馈给用户;因为在页面关闭,只有Service Worker被唤醒的情况下,没有前端界面,通知是与用户交流的唯一渠道。(这是伏笔)

缺点

看到上面的特性,我是十分动心的。可惜 PWA 终究不是原生应用,至少现在不是。美梦将醒。

Push Service 无法访问

最严重的问题。我们伟大的某虚拟混凝土建筑物阻挡了 FCM (Firebase Cloud Messaging),Google 的 Push Service 。因此它的推送前往用户端的路途就被阻断。虽然不是技术本身的问题,但是它占有推送服务的大部分,安卓的移动端大部分浏览器都使用 FCM 作为推送服务。在有梯子的情况下没有问题,但是这大大降低了可用性。

浏览器并非完全支持

标题重点批评 AndroidWindows 上的Firefox。它使用自家的推送服务(未被屏蔽),在控制台输出一切正常,有推送。但是Notification API完全不可用。 我尝试了 registration.showNotification (在事件内调用) 和 new Notification() ,均无法使用。上文也说了,没有通知的Push API是没有意义的。所以,这算是彻底断了后路了。

使用 Simple Push Demo (一个开源项目)可以很方便地获知浏览器使用的推送服务,和调试其是否正常。以下是各平台我的测试结果:

结言

见证如此不完善的新特性(其实早已实现),有点失望,不过也能理解。期待能见证 Web 生态越发完善,不仅仅是隐藏地址栏那么简单,而且集成了强大且跨平台的 API。不仅在体验上无限接近原生应用,也要在各方面有超越原生应用的特性。跨平台是大多 Web 技术的共性,我希望它的开发也应该尽量简单,这与功能强大并不冲突。

其实以后在网页中运行大型游戏也有可能......我对这个十分外行,不过我知道WebGLWebAssembly,也许 Web 应用的性能真的会飞升。

期望一个更开放,更统一的 Web 世界。

(明明是抱怨问题,我是如何把主题升华到这个程度的)