|
一、背景作为前端工程师,无论是开发还是线上环境,浏览器或是node,移动端或者PC端,经常会遇到一些bug,那么如何快速定位和解决问题呢,笔者准备了一份前端调试指南供大家参考。「文章大纲」:调试本身可以分为两个过程,「定位问题」和「解决问题」。而更重要的显然是如何快速的定位问题。本文将集中讨论如何「快速发现」并「调试问题」,至于如何解决问题,那就是开发本身的事情,无法一概而论了。二、调试工具方法2.1ChromeDevTools的使用Chrome的DevTools是最常用的调试工具,下面主要介绍下「Elements」、「Console」和「Source」三个面板的使用。2.1.1ElementsElements面板会显示目前网页中的DOM、CSS状态,且可以修改页面上的DOM和CSS,即时看到结果,省去了在编辑器修改、储存、浏览器查看结果的流程。Elements主要可以分为DOM结构以及元素(Element)内容两个子面板,下面主要介绍一下ElementsDOM$n开启Elements面板时,标记的元素后方总会有个==$0image-20220116212438893选中一个元素后再到Console面板输入$0,会发现刚刚选中的元素出现在Console中,如果再多点几个元素,还可以用$1、$2、$3、$4(到此为止)来拿到前几次选到的元素。另外在Console中对元素按下右键,选择RevealinElementsPanel可以跳到该元素在Elements面板中的位置,对Elements面板的元素按下右键则有Scrolltoview可以把视野滚到能看见元素的地方。想要在Console面板中用JavaScript操作元素时,$0就非常方便,另外也可以搭配console.dir($0)来观察元素的各个属性,如果在Console直接输入$0或是console.log($0)只会显示元素自身。image-20220116212412476inspect有时候一些dom节点会嵌套很深,导致我们很难利用Element面板html代码来找到对应的节点。inspect(dom元素)可以让我们快速跳转到对应的dom节点的html代码上。eg:在console输入inspect($('#app')),回车后便可以跳转到#app节点的html,进行审查元素2.1.2ConsoleConsole面板作为shell提示窗口用来和页面文档以及DevTools进行交互console对象前端说起调试,最常用的肯定就是console.log方法,但是console是一个对象,上面还有很方便的方法。console.table()可用于打印obj/arr成表格image-20220104154752095console.trace()可用于debugger堆栈调试,方便查看代码的执行逻辑,也可以帮助我们看一些库的源码image-20220104155335803console.count会印出这个标签被执行了几次,预设值是default,可以用在快速的计数。console.countReset与count 配套,用来重置,可用在计算单次行为的触发的计数。console.group()/console.groupEnd();为了在一大堆混乱的讯息中一眼看到自己的log,通常会这样做console.log("----start-----");console.log(object);console.log("---end---");虽然---是很显眼没错,但其实有更好的做法,用console.group可以自订Messagegroup的标签也可以多层嵌套,并用console.groupEnd来关闭Groupconsole.log("iteration");for (var firstLevel = 0; firstLevel 选择【Addsourcemap】第四步:拷贝Filesystem中的sourceMap地址。在chrome中修改代码并调试chromedevTools提供了localoverrides能力,首先,打开sources下的overrides面板;然后,点击【selectfolderforoverrides】选择修改后的文件存储地址;image-20220104172628695再然后,点击顶部的授权,确认同意;最后,找到入口文件,然后右键选择Saveforoverrides(一定要是原件,formatted后的版本不行),image-20220104173000023然后找到保存的文件进行修改,重新刷新页面后,修改后的代码就可以被执行了。2.2nodejs调试Nodejs使用ChromeDevTools调试--inspect-brk下面以调试webpack源码为例:node --inspect --inspect-brk node_modules/webpack/bin/webpack.js --env.production --config webpack-common.js执行bin中相应「启动文件」webpack.js打开chrome的开发者工具页面,如果看到node的「绿色图标」,点击就可进入调试。img2.3移动端调试VConsole与erudawhistle配合VConsole或者eruda,可以在任何环境下开启调试模式,在whistle中规则中配置相应域名下进行调试,以m.zhuanzhuan.com域名为例m.zhuanzhuan.com jsAppend://{eruda.js} jsAppend://{erudaInit.js}下载eruda.js,把eruda.js和erudaInit.js配置在values中image-20220104164430460image-20220104164328168这样就会在移动端开启调试eruda模式了。2.4微信WebView调试微信调试网页,正常来说你可以使用微信开发者工具[1]进行调试。它本质上和chrome://inspect方法类似,只是它为线上的微信包提供了debug模式,并将操作简单化。具体的使用方法可以参考官方文档:https://x5.tencent.com/tbs/guide/debug/season1.html2.5AndroidChrome真机调试如果你需要调试的Android手机版本>=4.4,则推荐使用chrome://inspect的方式进行调试,它能为WebView带来原生的开发者工具,可以方便的对代码进行断点调试。该方法需要满足以下三个条件才能使用:Android4.4+手机上开启允许USB连接设备进行调试客户端开启WebViewdebug模式//开启 webview 的 debug 模式webview.setWebContentsDebuggingEnabled(true);当满足以上要求之后,访问chrome://inspect,页面将显示您的设备上已启用调试的WebView列表。要开始调试,请点击您想要调试的WebView下方的inspect。像使用远程浏览器标签一样使用开发者工具。2.6iOSSafari真机调试如果你手机上安装的是DEBUG版应用,那么推荐使用Safari来调试,它能为WebView带来原生的开发者工具,可以方便的对代码进行断点调试。该方法需要满足以下三个条件才能使用:Mac:Safari->偏好设置->高级->在菜单栏中显示“开发”菜单勾选iOS:设置->Safari->高级->Web检查器打开最重要的是App必须开启DEBUG模式由于iOS有签名校验机制,真机正式包不允许SafariDebug,所以安装在真机上的包必须是测试签名打的包。需要联系客户端将我们iOS设备的ID写入到可信任设备列表中,然后使用iTunes安装客户端提供的测试包即可。当满足以上要求后,就可以在Safari->开发中看到自己的设备以及WebView中网页,点击后即可开启对应页面的Inspector,可以用来进行断点调试。2.7weinre调试当系统版本或者未开启debug模式导致上面的方法不可用时,可以考虑使用weinre[2]。weinre通过在页面中插入一段脚本,将页面的所有行为发送到服务上。首先我们需要安装并启动服务:npm install -g weinreweinre --httpPort 8000访问http://localhost:8000按照页面提示将debug脚本插入到页面中。访问页面后就会发现winere页面中出现了对应的请求记录,点击该记录即可跳到如下页面。可以看到这个就是一个网页版的开发者工具,可以方便的查看网络请求,控制台执行代码以及样式修改等。三、调试方法汇总方式优点缺点推荐场景移动端网络代理+whistle本地代理1、开发环境方便1、无法断点调试1、推荐开发环境使用whistle外部工具注入(vConsole.js或Eruda.js)1、方便2、无法断点调试1、推荐任何环境调试Android真机调试1、最接近真实环境,可以断点调试1、条件苛刻麻烦;2、仅限Android;3、不够方便1、实在找不到问题的保底手段iOSSafari真机调试1、最接近真实环境,可以断点调试1、条件苛刻麻烦;2、仅限ios;3、不够方便1、实在找不到问题的保底手段微信开发者工具调试1、可以pc一样方便的断点调试1、仅限微信;2、要提前将自己的账号加入到开发者账号中1、任何需要使用到微信的场景weinre(webinspectorremote)1、在whistle内有继承,比较方便;2、方便调试样式,选中即可得1、无法断点调试1、任何需要调试样式的场景四、调试一般步骤当出现异常时,按照这个基本逻辑排查,一般可以快速定位问题。4.1检查控制台是否报错可以快速确定页面不符合预期的原因是何种错误当前页面是否需要请求获取数据4.2是何种错误安全错误:与后端协商解决SyntaxError/ReferenceError/TypeError:编译阶段一般不会放过太低级的书写错误,可以认为这类错误都是写错了,一般很容易发现,找到错误堆栈进行解决数据不符合预期引起的错误(TypeError等):访问不存在的属性得到了undefined/null/NaN等值之后,会引发后续的异常。要先从检查数据入手。4.3当前页面是否需要请求获取数据网络请求是不稳定因素之一,可能会带来难以预料的复杂情况,出现问题的时候检查网络请求和数据的优先级很高。4.4.网络请求是否成功发送检查开发者工具Network/网络面板,查看需要获取数据的接口是否成功获取到数据。取不到数据的原因有两类,一类是责任在前端,一类是后端。主要通过请求提交的内容是否合法,接口返回内容是否符合预期两个方面判断。查看的关键点:方法是否正确URL是否正确跨域请求的Content-Type是符合要求请求体格式是否符合要求(JSON/Form)是否携带了身份信息合法请求没有得到预期返回,就找后端解决,请求与预期不符就是代码写错了,到错误地方查看代码。500等不该出现的异常:500大概可能是后端问题404URL写错权限问题:检查请求报文携带的身份信息4.5定位到代码应当执行的位置(大概即可)如果是控制台有错误信息的,利用sourcemap可以快速定位到问题出在哪一行。如果没有报错信息,就需要凭借当前页面的状态自己判断出问题的区域,按照代码执行的顺序排查。这一步可以利用的手段比较多,情况也更复杂,需要具体分析。查看代码运行状态:按照预期执行顺序检查代码检查渲染需要的数据是否与预期相同4.6按照预期执行顺序检查代码通过断点、日志等手段判断程序有没有按照自己想要的顺序执行,简单来说就是排查。4.7检查渲染需要的数据是否与预期相同检查运行过程中每一步的数据变化,是否与预期的相同。4.8异常代码一般分析方法「代码注释法」利用二分法思想逐行去注释代码,直到定位问题「类库异常,兼容问题」这种场景也会经常遇到,我们需要用可以调试页面异常的方式,如Safari,Whistle,vConsole查看异常日志,从而迅速定位类库位置,从而找寻替换或是兼容方案。「trycatch」如果你的项目没有异常监控,那么在可疑的代码片段中去TryCatch吧。「ES6语法兼容」一般我们都会通过Babel来编译ES6,但是额外的第三方类库如果有不兼容的语法,低版本的移动设备就会异常。所以,先用上文讲述的调试方法,确定异常,然后去增加polyfill来兼容吧五、总结写到这里整篇文章的调试方法就结束了。也许有很多不到位的地方,专业用词不严谨的地方,希望读者和我一起交流。非常乐意我的调试总结给予前端人受用。Reference[1]微信开发者工具:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html[2]weinre:http://people.apache.org/~pmuellr/weinre/
|
|