相关文章推荐
会开车的钱包  ·  Python ...·  1 年前    · 
强健的围巾  ·  正则表达式 - ...·  1 年前    · 

前阵子公司内部做了一个数据大屏,而后为了方便网点使用,让安卓端的同学开发了apk,可以让用户通过apk访问大屏。

然而apk并没有内置浏览器,而是直接打开设备自带的浏览器,而用户的设备又是各种各样,随之而来的就是兼容性问题。

这其中就遇到了一些用户打开apk后,白屏的现象

而我们内部的设备都可以正常使用,所以这个白屏问题必然是用户自带的浏览器版本太低导致的

我们也与组长交流过,就算这次大屏问题解决,后续也可能会有其他兼容性问题,所以不如让apk内置一个浏览器,后续也不会有相关问题,但是这个方案被作为备选方案,没办法只好硬着头皮上

首先既然白屏了就一定会有报错,解决这次白屏的过程中花费了太多的时间在查看报错上

vconsole

首先想到的是引入vconsole,想直接通过vconsole查看报错信息,奈何用户的设备上连vconsole都没有出现

而后偶然发现我们内部的手持设备打开apk也是白屏,不同之处在于手持设备打开有显示vconsole

而后就像找到救命稻草一般对着手持设备调试,然而即便手持设备有vconsole,vconsole中也没有log出错误信息或者其他有用的信息

此时就像无头苍蝇般对着代码进行注释,发布测试环境,查看现象,如此反复,花费了大量的时间,最后发现有些代码注释的情况下页面能够正常展示,不注释就白屏

这时候我就非常困惑,假如是代码兼容性问题为何vconsole中没有相关的错误信息

另外因为我用的是umi脚手架,本身就已经集成了兼容性相关的配置 也查看了打包之后的代码产物,故而我总认为代码兼容性上应该不会有问题

如下是vconsole的信息,了解umi的同学应该知道umi的app.tsx中暴露了一个patchRoutes函数,而我在该函数里log的信息这里都没有展示

所以我一度以为是umi自身的问题,但是翻遍了issue和各个论坛也没有解决

vconsole表现如下

查看错误信息

后来我用了另一种查看错误信息的方式,在document.ejs中引入一段捕获错误的代码,而后把错误信息放到页面上,如下

<!doctype html>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi" />
  <title>数字大屏</title>
</head>
  <div id="user-agent"></div>
  <div id="test-content">测试内容</div>
  <div id="root" class="digit-front-app"></div>
</body>
<script>
  function infoToBody(thing) {
    const div = document.createElement('div')
    div.innerText = thing
    document.body.insertBefore(div, document.getElementById('test-content'))
  var myLog = window.console.log
  var myError = window.console.error
  window.console.log = function(thing) {
    myLog(thing)
    infoToBody(thing)
  window.console.error = function(thing) {
    myError(thing)
    infoToBody(thing)
</script>
<script>
  var targetEle = document.getElementById("user-agent")
  targetEle.innerText = window.navigator.userAgent
</script>
<script>
  window.addEventListener("error", function(error) {
    console.log('error', error);
  var otherMsg = 'message: ' + error.message + '\n' + "filename: " + error.filename + '\n' + "lineno: " + error.lineno + '\n' + "colno: " + error.colno + '\n' + "error: " + error.error + '\n'
  alert(otherMsg)
</script>
</html>

这里第一段代码是劫持了log和error,把log和error的信息展示到页面上

第二段是把设备信息展示在页面上

第三段是捕获错误,把错误信息展示在页面上

在此操作之后,使用手持设备访问大屏,终于发现了报错信息

cannot read property includes of undefined

这里还是想吐槽一下为毛这种信息vconsole没有打印出来呢

主要信息如上

而在我的代码中,用到includes的地方也不过三个

['09020102', '09020101'].includes(errorCode)
window.origin.includes('sit')
service?.includes('-dr')

把代码翻看出来后,才发现第二处的window.origin有问题,

查看相关资料后才发现两者是有区别的

window.origin

该属性是只读的。

origin的值是当前页面环境的源。

当源不是http和https协议,比如是file协议,则返回的值是null。

location.origin

表示的是当前页面的URL的源。

两者的兼容性也有区别

可以看到window.origin在chrome87以下的版本都不支持

而信息中显示用户的浏览器版本为chrome39

所以原本的写法也理所当然的报错了

到这里我就把window.origin 改为 window.location.origin

这时手持设备终于可以正常访问了

而后我就把修复后的代码发到测试环境让用户尝试一下

本来以为事情应该就这么告一段落了,

但是用户反馈依然是白屏。。。

这时候我就懵了。

因为此时又出现了那个问题,看不到错误信息。因为我们内部的设备都正常访问,又没法远程网点的大屏设备

一筹莫展之际,我发现caniuse网站上有个这么个东西

这个看起来像是可以模拟浏览器环境,于是乎我点进去(翻墙),发现了browserstack这么一款浏览器兼容性调试工具,

但是browserstack是收费的,免费的使用时间只有一分钟。。。 我还没来得及输入网址就给我弹没了

后来又查找了其他兼容性工具,有一些可以免费使用几天甚至半个月,但是环境太少了 chrome最低都有99,无法达到目的

而后在知乎上无意发现了这么个网站

www.browserling.com/

每次会话可以使用3分钟,一天5次,虽然时间不长,但是也算勉强够了

之后用该工具打开网址,发现document.ejs中的部分代码报错了

  function infoToBody(thing) {
    const div = document.createElement('div')
    div.innerText = thing
    document.body.insertBefore(div, document.getElementById('test-content'))
  var myLog = window.console.log
  var myError = window.console.error
  window.console.log = function(thing) {
    myLog(thing) // 此处报错
    infoToBody(thing)
  window.console.error = function(thing) {
    myError(thing) // 此处报错
    infoToBody(thing)

说实话我现在也不太懂这个为啥报错,报的错误信息我也忘了,后来没看出个所以然,索性把上面那段代码中多余的部分删掉

  function infoToBody(thing) {
    const div = document.createElement('div')
    div.innerText = thing
    document.body.insertBefore(div, document.getElementById('test-content'))
  window.console.log = function(thing) {
    infoToBody(thing)
  window.console.error = function(thing) {
    infoToBody(thing)

如此就不报错了,当然这些代码只是测试环境上使用,生产本身就需要去掉

如此整个白屏问题基本结束

当然还需要注意umi的打包配置也需要调整,如下

// 目标兼容环境  
targets: {
    chrome: 37,
    android: 5,
// type默认为none,即不对node_modules中插件进行兼容性打包,提升打包速度,但是我们这里需要设置为all,对所有第三方库进行兼容性打包
  nodeModulesTransform: {
    type: 'all',

最最重要的一点就是想尽一切办法查看报错信息,白屏一定有错误原因,没有拿到报错信息的话就无从下手,结果只能是各种盲猜,白白浪费时间

  • 私信