前端调试实践

作者:京东零售 黄泽平

前言

在日常调试问题中,相信我们很多人都是用console去排查相关的问题,虽然问题也可以排查出来,但是有时它的效率并不高。这篇文章主要讲解关于断点和一些日常调试技巧的内容,方便你在日后调试问题中,能在不同的前端场景应用不同的调试方式,翻倍提高你解决问题的效率

 

1 sources面板概览

source面板是我们断点调试经常用的到的地方,我们可以先大概认识一下它长什么样子,大概有什么功能

 

左侧区块:包含了Page、Overrides、Snippets等5个功能块,其中Page可以查看该网页已加载的所有资源
中间区块:可查看、编辑资源文件,也可查看图片类型的文件;同时可在其文件左侧进行断点等相关操作
右侧区块:断点调试时的区域,可以开始、下一步等断点操作,同时可以查看断点调试时的变量值、调用栈等信息

 


 

 

当展示开发者工具的区域过小时,它会自适应调整布局

 


 

 

2 常用的断点方式

我们平常最经常用的可能就是代码行断点了,但是有时用它调试问题并不是效率最高的。chrome中还包含了其他的断点方式,我们可以在不同的场景应用不同的断点进行高效调试。

 

2.1 代码行断点

代码行断点,当代码运行到当前行之前,代码会暂停执行

 

2.2.1 点击Sources面板中的源代码的行号

当行号列对应行出现蓝色图标,即为打断点成功。在右侧的Breakpoints中,会出现你有打断点的信息,展示了对应的行号,也可以让你取消、勾选、编辑、删除断点

 


 

 

2.2.2 断点操作按钮含义

我们可以在右上角看到6个控制断点的操作按钮,分别对应着不同的操作

 


 

 

 


 

恢复执行

 

 


 

单步执行

 

 


 

进入函数调用

 

 


 

跳出函数调用

 

 


 

让该断点失效

 

2.2.3 行断点实战

在开发过程中,用例列表刚开始还可以加载出用例,怎么突然没有数据返回了。查看接口发现moduleIds参数出现了问题

 


 

 

于是对相关代码行设置了断点,当执行到149行的时候moduleIds的值是 [4611,5417]

 


 

 

可当执行到152行的时候,moduleIds的值却是 [undefined]

 


 

 

原来是这两处逻辑冲突了,后面的逻辑覆盖了前面的逻辑

 


 

 

问题很快排查出来。如果用console.log的话,可能要在代码中写好几个console,保存后,刷新浏览器打印,排查完,可能还需要去删除掉,所以遇到一些问题排查效率就提高了许多

 

2.2 Logpoint日志点

有时候,我们并不需要像代码行断点一样,把我们的代码暂停。我们只需要像console打印一下相关的信息,不要中断我们的代码执行。这个时候我们logpoint就派上用场了,它的语法跟console.log一样,我们可以快速得写好我们的调试信息,而且不用像console.log一样干扰我们的代码,也不用过后还得惦记着去删除它

 

比如下面的logpoint,其会显示粉红色的图标,代码执行到它的时候,它会在console面板中打印

 


 

 

注意,我们可以使用点击esc快捷键,快速得调起我们的console面板查看信息

 


 

 

2.3 异常断点

当我们的代码有错误,引发对应的异常报错时,我们有时会比较难快速定位到是在哪里出现了问题。我们可以利用异常断点,在发生异常的时候立即进行断点,从而快速找到发生问题的代码,并且可查看相关的变量、调用栈来帮助我们排查问题。

 

异常断点分为两种,可分别在在未捕获和已捕获的异常处进行断点

 

2.3.1 Pause on uncaught exceptions

比如下方代码中,aa要访问一个不存在的变量,这里是有问题的。这也是我们在代码中经常会遇到的问题

  const handleClick = () => {
    const aa = null;
    const bb = aa.size;
    setIsClicked(true);
  };

 

我们可以在Breakpoints中勾选Pause on uncaught exceptions,当代码执行到这些有异常的代码时,自然会暂停

 


 

 

 


 

 

2.3.2 Pause on caught exceptions

下方代码已经异常进行了捕获,这种情况可以勾选Pause on caught exceptions来对捕获到异常代码行暂停进行处理

  const handleClick = () => {
    try {
      const aa = null;
      const bb = aa.size;
      setIsClicked(true);
    } catch (error) {
      console.error("1-zp-error:", error);
    }
    
  };

 

 


 

 

2.4 事件监听器断点

当用户发生交互时出现问题,这时我们就可以添加事件监听器添加断点来捕获这些事件以检查交互时的问题。可以在Source面板右侧的Event Listener Breakpoints中勾选相应的事件

 


 

 

2.5 DOM 更改断点

使用频率不高,研究如何操作dom的特定场景才有有用

 


 

 

3 调用栈

当我们在查看、调试一段比较复杂的代码时,我们有时很难快速得从代码文件理清其调用关系。此时,我们可以利用调用栈来帮助我们快速理清逻辑,快速排查问题

 

3.1 栈

栈是一种数据结构,其内部的的元素满足后进先出的特点,我们可以对其进行入栈、出栈的操作

 


 

 

3.2 调用栈的应用

比如我在caseReviewListTable文件的第206行代码中打了一个断点,当代码执行到这部分逻辑的时候,他就自然会暂停

 


 

 

我们此时可以看到右侧的Call Stack中从上到下排列着函数调用栈信息,如下图我们可以查看到,在执行到该断点的时候,我们已经先在其他文件的handleRefreshCaseReviewList、handleSearchCase函数中执行过相关代码了。我们可以点击函数名右侧的文件地址,快速查看对应的代码,这样子,我们对其调用逻辑清晰了许多,排查问题的效率自然会提高

 


 

 

3.3 anonymous 匿名的

我们在看上面的代码中,发现一个anonymous栈帧,他代表了是一个匿名函数,即没有名称的函数

 


 

 

比如下面代码我们加个 setTimeout,也会在调用栈生成一个anonymous的栈帧

 


 

 

3.4 console.trace()

除了通过断点来查看调用栈,有时我们也使用 console.trace() 来输出当前的函数调用关系,比如我们在下面代码对应的位置加上console.trace(),我们就可以看到其当前位置的调用栈信息

 


 

 

4 Snippets

在浏览器中,如果你在调试中,有一些公共的逻辑需要经常用到,你可以把其代码片段保存在Snippets中。当你在任何一个页面需要运行它的时候,可以直接运行它

 

比如我们想要获取当前页面的所有图片链接,我们可以将这段代码存储起来

 


 

 

需要用的时候,我们直接快捷键Command+P输入!字符,搜索你要执行的代码片段名称,选择以后即可执行

 


 

 

5 Overrides

5.1 替换响应内容

如果有些异常数据导致页面发生问题,我们可以直接利用那份异常数据,在本地进行调试。当然,如果后端接口还没好,我们知道结构也可以mock数据

 

比如我们现在有一个/api/v2/review/list/getCaseReviewList接口

 


 

 

我们右键,选择Override content替换接口内容

 


 

 

选择以后,会需要你选择一个存储这些替换文件的文件夹

 


 

 

授权

 


 

 

我们将我们的模拟数据填充在这里,即可在页面中调试我们的UI和相关逻辑了

 


 

 

其中,被覆盖的接口会显示紫色的标识

 


 

 

如果我们不需要了,根据情况禁止、删除、清空都可以

 


 

 

5.2 替换响应头

如果有些场景,需要添加或者修改响应头,也可以进行自定义修改

 


 

 

选择Add header,然后自己添加修改对应的响应头数据

 


 

 

6 其他调试技巧

6.1 复制、粘贴、拖拽元素

当产品需要对已经开发好的页面进行一些位置的移动调整的时候,我们可能对代码有一个比较大的改动才可以给她看到效果,但是过后我们又得把代码改回去。这时,我们可以利用chrome提供给我们的能力,复制元素、粘贴以及拖拽元素,来实现快速的页面布局调整,给产品看到效果,又不需要改代码

 

比如我们复制今日工作这个区块,然后粘贴在你需要放置的位置容器下进行粘贴

 


 

 

粘贴以后,我们长按元素,进行拖拽调整位置即可

 


 

 

6.2 全局搜索

6.2.1 全局搜索文件/目录

当我们要快速调试一个文件的代码的时候,直接按Command+P快捷键调起搜索浮层,输入文件名或者文件路径名,即可快速找到对应的文件,选择点击以后会到达sources面板打开对应的文件

 


 

 

6.2.2 全局搜索代码

当我们有对应的代码关键词,想打开它对应的文件。chrome提拱了一个全局搜索代码的功能,我们可以打开对应的search面板

 


 

 

比如我输入“name: '计划列表',”这个关键词,它会在这个页面已经引入的资源搜索对应的代码关键词,然后把匹配的文件展示在下方,我们就可以立即选择然后打开对应的代码文件了

 


 

 

6.3 网站样式风格概览 CSS Overview

当我们看到一些优秀的网站的时候,我们想快速查看借鉴该网站样式信息的时候,我们可以借助CSS Overview这个功能快速得到相关信息,非常好用有趣

 

比如我们拿花瓣这个网站做例子,我们打开开发者工具,开启CSS Overview面板

 


 

 

然后按“Capture overview”开始收集信息

 


 

收集好以后,我们便可以从颜色、字体等维度获取到该网站的样式信息

 


 

 

另外,当我们点击对应的色块的时候,它也会列出用到的地方,点击对应的元素也会快速定位过去

 


 

 

6.4 折叠屏手机适配

如果我们的开发场景中,需要适配折叠屏手机,比如像下面的三星Galaxy Z Fold5,那么我们的chrome也可以派上用场

 


 

三星Galaxy Z Fold5

 

我们需要进入对应的移动端调试模式,选择对应的移动端设备

 


 

 

选择折叠场景,然后我们即可进行调试了

 


 

 

调试Surface Duo设备

 


 

 

 


 

 

7 学习资源分享

前面讲了这么多,其实只是抛砖引玉,还有很多东西是我们没有讲到的,我们可以通过下面的渠道进一步的了解、应用相关的知识和工具

 

7.1 Chrome DevTools

包含了Chrome 开发者工具相关功能的详细介绍还有相关的实践应用场景

 

7.2 Google Chrome Developers - YouTube

Google Chrome Developers的YouTube频道,视频展示了相关的新功能以及最佳实践

 

7.3 浏览器工作原理与实践

极客时间这门课从浏览器的渲染、javascript执行机制、V8工作原理、安全等相关视角去讲解浏览器的相关内容,从而让我们对前端的体系有一个更全的理解

 

8 总结

本文介绍了断点调试、sources面板和日常使用到的一些调试技巧,帮助我们在后续的开发中,提供一些新角度、新方式来解决问题,翻倍提高我们的开发效率

posted @ 2024-11-14 11:12  京东云开发者  阅读(18)  评论(0编辑  收藏  举报