背景

收到用户反馈说App里面跳转H5页面,顶部进度条走完,显示空白,没有任何提示,sentry监控服务也没有收到任何报错。

只有部分旧版本设备会出现这种情况,比如Android 5.1, iOS9,新机型是没有问题的。

问题排查

由于监控服务没有接收到异常信息,排除网络问题就两种可能:没有捕捉到异常或者监控根本还没有加载出来。考虑sentry js-sdk的异常捕捉能力已经非常完善,所以更大的可能就这个页面加载就出错了。

因为是React但也应用,首页排查index-template.html中是否存在有兼容性问题的代码。

>. 排查发现页面底部有使用let字段,也就是用了es6语法。这个js的位置在最底部,讲道理不会导致整个页面任何内容也没有。

修复这个问题,上线后依然是空白页。

>. 想办法找到一台可以浮现问题的Android设备,通过chrome://inspect调试,找到报错信息,提示Buffer.prototype.slice is readonly,不能修改。由于项目体积太大webpack-bundle-analyzer无法使用,只好从yarn.lock入手,顺藤摸瓜找到这个代码来自buffer这个包,由webpack3通过node-libs-browser引入,并打包进项目中。

先撇开buffer为什么进入代码不谈,为什么buffer在为Buffer类型扩展slice方法时候被拒绝。显然是在这之前就有代码改了Buffer的原型。

查找发现在html>head中引用的的aliplayer-2.8.2中由对Uint8Array(上面提到的Buffer的实现方式之一)增加slice方法:

我们知道,第一点:通过defineProperty增加的属性,默认writeable=false;第二点:这段代码扩展slice方法的前提是浏览器不支持Uint8Array.slice()[TypedArray.prototype.slice()];最后一点,Buffer的补丁代码在入口业务代码前面。

所以也就出现了老版本webview无法显示网页的问题,以及上面的各种情况。

方案

方案1: 修改sdk代码,加上在defineProperty时候,加上writable: true

方案2: 关于webpack为什么把node用的buffer放到生产代码中,目前没找到明确解释,在文档中找到node配置项,功能是让之前为node写的项目可以跑在浏览器里面。可以配置node: { Buffer: false },就不会打包Buffer的polyfill到生产代码了。(当前是个历史项目,这个不知道会动到什么,不敢动)

最终方案

阿里云播放器后置按需加载,先加载项目入口及其携带的polyfill,这样及解决了当前问题,也优化了资源消耗。

按需加载方案:播放器组件通过document.body.appendChild方式加载aliplayer,然后在script.onready之后,再处理播放相关业务。可以封装为Promise类型返回。github上代码也很多,可参考loadScript同时处理下兼容性

avatar
  Subscribe  
提醒