当前位置: 首页 > Web前端 > vue.js

技术总监:尽快解决这个ios11白屏问题

时间:2023-03-31 21:13:50 vue.js

事情是这样的。上周,一位用户使用手机访问我们的页面并出现白屏。客服还专门开了一个交流群。前端组长跟我说,你可以帮忙解决这个问题。继续做吧,但是这个问题有点麻烦,需要一段时间才能解决。作为一个成熟的程序员,让客服同学先安抚用户。毕竟我们公司是以客户为中心的,我们也预留了一些时间来解决问题。没想到,我们正在紧急处理问题,客户打电话给技术总监。好家伙,导演发话了。这个问题很严重,需要尽快解决。所以怎么回事,继续加急处理。从客服处了解到,用户手机是ios11系统,其他手机不会出现白屏问题。初步判断是兼容性问题。要系统地分析白屏问题,首先要梳理整个页面的访问链接,这是面试中经常被问到的问题:输入网址到显示页面之间发生了什么?请看下图。1why:为什么会出现黑屏?首先,只会出现ios11,也就是说没有返回html。从现象可以确认页面上显示的是标题,但是没有内容。通过抓包,发现确实有返回的html。基本可以确定问题出在浏览器层,也就是上图中红色部分。2why:为什么没有内容?抓包发现有返回的html,还返回了入口js,即app.xxx.js和chunk-vendors.xxx.js。有js,但是没有内容,有两种可能:入口js没有执行,入口js执行报错,导致后面渲染页面的代码没有执行,再查看是否有错误在日志系统上报告的消息。检查了一下,发现没有报错信息。可能是上报系统没有上报。好吧,我只能用vConsole(手机h5调试神器)大法了。使用起来非常简单,直接在html的头部添加如下代码即可(注意:一定要在入口js之前执行,否则可能抓不到错误):用ios11手机打开测试页面发现链vConsole按钮不出现。它是否与vConsole存在兼容性问题?几经测试,换成低版本的vConsole后,终于可以调试了。刷新页面,打开vConsole,但是找不到具体的报错信息,只有一个简单的Scripterror。但是至此,确定是js报错导致了白屏,那么接下来就是想办法获取报错的具体信息了。3why:为什么只显示Scripterror?原因其实很简单。js、css等静态资源放在CND上。静态资源的域名和页面的域名不一样,存在跨域问题。了解过跨域的同学都知道,由于浏览器安全策略的限制,跨域脚本报错时,无法直接获取到详细的错误信息,只能得到一个ScriptError。找到原因后,就很容易解决问题了。配置两件事:配置响应头:Access-Control-Allow-Origin,将crossorigin属性添加到script标签。白屏页面使用vue框架,只需要在vue.config.js中添加crossorigin:""配置即可,然后查看报错信息,发现入口js的getCurriculumTime方法报错。我们上面判断是兼容性问题。这种方法是否存在兼容性问题?根据报错信息查找入口js,结果是一个async方法。换句话说,es6语法并没有被翻译成es5。但是.browserslistrc已经配置了ios>=8,为什么不翻译呢?4why:为什么es6语法没有翻译成es5?vue.config.js中有一个transpileDependencies配置,VueCli官方文档是这样解释的:Type:boolean|数组<字符串|RegExp>Default:false默认情况下,babel-loader会忽略node_modules中的所有文件。您可以启用此选项以避免构建代码中未翻译的第三方依赖项。但是,转译所有依赖项可能会减慢构建速度。如果你对构建性能有顾虑,只能翻译一些特定的依赖:给这个选项传递一个数组,列出需要翻译的第三方包名或正则表达式。经过排查,发现getCurriculumTime确实是node_modules的next依赖中的一个方法。白屏页面在这个依赖中使用了几个vue组件。如果找到原因,就很容易解决了。直接依赖包的包名放在transpileDependencies数组中,类似如下:transpileDependencies:['@xxx/xxx']现在问题可以解决了,激动的快要报告组长了。等等,作为一个成熟的程序员,我们先测试一下自己。好家伙,阮了也没用,白屏还是白屏,报错还是一样的报错。会不会是transpileDependencies的配置没有生效,果然,搜索编译后的代码,async等es6语法还在。再看transpileDependencies配置,可以是boolean,可以是string,也可以是正则数组,多次试过true,正则化不生效。用户不断询问进度。不行,得先停下来深挖原因,先找到简单的解决办法。既然node_modules下的package默认是不翻译的,那就直接引用组件的vue代码,试一下就可以了。好了,问题解决了,我们喝点水,摸摸鱼儿休息一下。5why:为什么transpileDependencies配置没有生效?虽然暂时解决了白屏问题,但是项目引入了很多依赖。只要有一个没有被翻译成ES5的依赖,就可能会出现问题,就像一个不确定的定时炸弹。一旦爆炸,人们就会熬夜加班,头发也会掉光。作为一个成熟的程序员,我们要彻底解决问题。为了找到transpileDependencies配置不生效的问题,翻了一下源码。vscode全局搜索了node_modueles/@vue文件夹,发现了蛛丝马迹。//@vue/cli-plugin-babel\index.jsfunctiongenTranspileDepRegex(transpileDependencies){constdeps=transpileDependencies.map(dep=>{if(typeofdep==='string'){constdepPath=path.join('node_modules',dep,'/')returnisWindows?depPath.replace(/\\/g,'\\\\')//Windows样式路径的双重转义:depPath}elseif(depinstanceofRegExp){returndep.source}})返回deps.length?newRegExp(deps.join('|')):null}这段代码大家都能看懂,我就不解释了。看一下使用这个方法的地方:两段代码意思是会翻译transpileDependencies配置中的依赖,官方文档没有骗人。问题是在我的电脑上编译会翻译,但是在服务器上编译不会翻译。想不通,搜索看看有没有人遇到过。找了半天,都说没有找到病根,曲线救国解决问题。但是有个哥们说不能用cnpm安装依赖。好家伙,我电脑上用的是npm,服务器上用的是cnpm。6why:为什么cnpm安装依赖没有翻译?查了一下cnpm和npm的区别,都说cnpm是国内源,没有其他有用的信息。但是从问题来看,cnpm和npm还有其他的区别。为了找到根本原因,在源代码中添加一些日志并进行调试。//vue.config.js翻译node_modules下的所有@xiaoe依赖transpileDependencies:[/[/\\]node_modules[/\\]@xiaoe/]看结果:npm:@xiaoe依赖会被正常翻译cnpm:all@xiaoe没有翻译对比,很容易发现cnpm安装的包有_字符,路径变了,正则模式匹配不上,所以通过cnpm安装的包不会翻译。解决方案找到根本原因,问题就解决了。方法一:修改正则表达式匹配cnpm安装的依赖路径即可。//如果要匹配其他包,只需将@xiaoe换成其他包名即可transpileDependencies:[/[/\\]node_modules[/\\]_?@xiaoe/]方法二:使用npm安装依赖方法三:把node_modules用正则表达式匹配就可以了,但是这样会减慢编译速度,需要根据实际情况选择合适的方式。transpileDependencies:[/[/\\]node_modules[/\\]/]综上所述,采用6w思路彻底解决了白屏问题,过程可能有点繁琐。实际操作过程比文章描述的要曲折,但基本上是完全看懂了。还有一点我想跟大家分享的是,由于工作繁忙,我们往往解决了问题,没有继续追根究底。这对技术人员来说可不是什么好事。追根究底,虽然需要更多的时间,但是可以提高看问题的深度和彻底解决问题的能力。终于,花了一天的时间整理了这篇文章。如果对大家有帮助,不妨来个一键三连。如果大家觉得有什么不对或者不详细的地方,欢迎大家在评论区讨论,我会抽空回复大家的,哈哈哈。