工作实录:PWA应用在IPad上不能正常运行的调试全过程

1,503 阅读6分钟

阶段1 - 发现问题

1. 收到用户反馈,IPad离线情况下某些不能正常显示

  • 试图在电脑上复现此问题,但是没有成功
  • 在Ipad上复现问题,也没有成功
  • 与PA沟通确认问题

问题只发生在IPad 系统版本15.x的设备上,且加载应用为桌面应用(此应用区分桌面端和手机端)

2. debug问题

  • 成功复现问题
  • 发现现象
    • 安装时候看不到应用图篇
    • 安装之后service worker 状态正常
    • 图标文件请求失败
    • svg 图标请求失败
    • 首次打开白屏

3. 分解问题,分步修复

3.1 安装找不到应用图标

  • 查询图片支持情况变化

image.png

所以,从上面的信息看上去,link标签优先级最高,永远起作用!(坑)

但是,之前的代码里面是有指定图标的。

怀疑 1 尺寸不合适?

所以更新尺寸为144x144 参照于Angular.io

image.png

测试之后发现并不起作用

怀疑 2 难道是144尺寸不合适?

那我就给一个全尺寸!

image.png

于是,加上了所有尺寸的设置。但是结果仍然是不起作用。

由此可知,方向不正确,但是正确的方向在哪里?

  • 试图在本地复现问题

监狱应用程序存在权限校验所以,所以打算测试基本的happy path. 注释掉了所有的UI,只保留了入口页面。编译,启动本地服务器。使用IPad打开本地应用,可以看到图标,安装正常。

这里证明了入口文件的图标设置是没有问题的, 至少修改之后的图标设置是正确的

怀疑 3 问题产生在代码内部?

查看近期的修改历史,发现了入口修改新增加了 APP_INITIALIZER

image.png

怀疑这段代码的原因是,Service Worker 的注册发生在软件初始化的时候,而这里的修改影响了初始化。

image.png

所以,我注销了这部分代码,本地启用Proxy试图验证猜测。结果发现,一切正常。

难道这就是问题的原因?

为了验证这个猜测,把测试代码推到测试服务器。使用线上测试环境来验证问题。

结果是,然并卵

但是,监狱之前认定问题出在代码内部,所以

猜测 4 是不是最近新增的 Guard有关系? (这里其实方向已经错了)

所以注释了Guard相关的代码,推到线上测试环境进行验证。

结果还是,然并卵

此处暂时迷失方向

偶然发现的转机

在使用MacBook debug 的时候,发现Safari自带的Dev Tool是真的不好用。service worker 的请求基本上看不到。所以试图借助第三方工具来抓包。

但是公司的电脑和网络对数据包都进行了二次加密,完全看不到任何有用的信息。

所以,晚上回家使用自己的电脑和网络进行抓包。这时候发现了问题的根源。

Safari 向服务器发送了错误的User Agent

先简单介绍一下我们应用的工作流程:

image.png

前端的请求都会经过Router来做判断,判断的依据就是User Agent.是手机的User Agent 会将请求转发到手机对应的后端,是桌面端请求的会转发到桌面端对应的后端。

问题就出在Router这里,桌面端的Manifest图标在经过Service Worker请求的时候发送的User Agent不正确,请求被转发到了错误的后端,造成资源请求不到。

Service Wroker 请求Manifest图片携带的User Agent:

image.png

Service Worker 请求其他资源时携带的User Agent:

image.png

所以,修改了Router部分对User Agent 处理的代码之后,图标问题就被解决了。讲道理这是Safari的Service Worker部分的BUG。

  • svg文件缓存失败问题

image.png

这两个问题其实是一个问题,就是在写路径的时候加了一个斜线。

image.png

原本这样写是没有问题的,Assets确实在根路径下。但是,后来修改了项目的部署路径。

手机端部署在 Https://domain/mobile/XXXXX

电脑端部署在 Https://domain/desktop/XXXXX

所以对应的资源就不在根路径下了。

  • svg icon 不能正确显示问题

我们使用的部分svg 图标是下面的写法,这种写法在加载的时候会请求svg文件名#id

但是这个请求Service Worker其实并没有缓存,所以会在离线的时候还试图发送请求。

image.png

上面的修改依赖把svg template 定义到root html 内部才能这样写。 而且这里是自定义的table cell 所以不支持mat-icon

  • 打开之后白屏问题

原因一:推测

从Safari 浏览器添加到桌面之后,直接打开桌面图标。这时候Safari 浏览器的页面和Service Worker 工作中。并且新起程序会认为Service Worker 已经启动,新页面资源加载会排在所有缓存资源的队尾执行。

这就是为什么有时候经过长时间等待之后会看到页面被加载。

原因二:

打开新图标之后,Safari从当前域下不能获取SID(token),由于没有 sid 这时候会跳转到登陆服务器。但是这时候Service Worker是正在工作的。所以,原本的域名跳转会被Service Worker来fetch,这时候就会报错,页面就死在当前状态。

原因三:推测

这种情况是类似于原因一,有时候即使经过长时间的等待,页面依然白屏。dev tool能看到的请求也只有页面的请求和极少数的几个资源请求,但是都没有执行。怀疑是Service Worker 一直pending在一些请求上。但是这些请求实际上已经完成了。

所以,针对这个问题,目前的办法就是在安装应用之后,主动杀掉浏览器的页面。然后再打开应用。

补充: Chrome 和 Safari 针对PWA安装之后的标签页的处理逻辑不一样。 Chrome 会完全复用浏览器已经加载的所有资源和Service Worker. Safari 会认为是一个新的物理层,会重新缓存所有的资源。对于Service Worker我个人理解是也没有复用。 安装应用启动的时候,由于当前域的一致,导致的冲突造成的属于自己的Service Worker没有起来。我这么认为的依据是浏览器内Service Worker缓存的资源,安装应用的Service Worker一样要缓存一遍。

总结

此问题其实并不具备代表性,只是我们在PWA商用化上的一些特殊情况。

不过实话是说,Mac在这方面是有些坑的。就像User Agent 这种问题,Safari 自己的dev tool根本抓不到。

如有错误,欢迎指正。