devTools之Source面板

560 阅读7分钟

Source面板作用主要有两个:查看网页源码和调试代码。

它的功能划分如下图所示: image.png

下面介绍下Sources面板的作用:

查看网页源文件

如上图所示,顶层top代表的是整个HTML框架,第二层代表的是一个origin,其他层则是加载的js等资源,单击文件可以在右侧的编辑器中查看其具体内容。

调试代码

先介绍下断点的类型:

断点类型

Line-of-code

行断点是我们平时开发中使用最多的断点类型,设置步骤如下:

  1. source面板的文件查看窗口中根据webpack打包规则找到源码对应的文件
  2. 点击代码编辑窗口左下方的花括号{}格式化代码文件(①本地开发时代码没压缩,可以省略该步骤;②还有个一劳永逸的办法,在devtool settingExperiments勾选Automatically pretty print in the Sources Panel
  3. 点击目标行,目标行上会出现一个蓝色图标,此时就设置成功了,在调试窗口的Breakpoints中看到刚设置的断点。如下图所示: image.png

除了在chromedevTools中设置行断点外,我们还可以通过debugger在代码内设置行断点,需要注意的是,如果调试功能被禁用了,则该语句不生效。生产环境禁用debugger功能是通过uglifyjs-webpack-plugin来实现,配置如下:

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
# ....
new UglifyJsPlugin({ 
    uglifyOptions: { 
        # ...其它配置
        compress: { 
            # ...其它配置
            drop_debugger: false 
        } 
    } 
})

Conditional line-of-code

当在循环体内设置了断点的时候,那么每次循环都会进入断点,会变得比较麻烦。如果我们明确知道是哪次循环有问题的时候,则可以使用条件断点。举个例子:

const arr = [{
    name: 'haha',
    age: 10
}, {
    name: 'heihei',
    age: 20
}, {
    name: 'xixi',
    age: 18
}]
arr.forEach(item => {
    console.log(item)
})

如果我们明确知道当age大于18的时候数据有问题,那么我们可以这样设置条件断点: 条件断点.gif

DOM

Element面板找到要打断点的目标元素,右击,可以看到DOM元素的断点类型,如下图所示: DOM断点类型.png

  • subtree modifications:当前选中的节点的子节点被移除或添加,或者子节点的内容被改变时触发
  • attribute modifications:在当前选定的节点上添加或删除属性或属性值更改时触发
  • node remove: 当前选中的节点被移除时触发 举个例子,在浏览器中打开下面的代码:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #app {
      width: 100px;
      height: 100px;
      background-color: blue;
    }
  </style>
</head>
<body>
  <div id="app"></div>
  <button id="btn">修改div的宽为200px</button>

  <script>
    document.querySelector('#btn').addEventListener('click', () => {
      const div = document.querySelector('#app')
      div.style.width = '200px'
    })
  </script>
</body>
</html>

div设置attribute modifications断点,如下所示: DOM打断点.gifDOM断点设置成功后,可以在右侧的DOM Breakpoints中查看。 DOM断点设置成功

ps: 日常开发中我们基本都是使用的第三方框架,多次测试发现DOM断点设置成功的概率很低...

XHR

xhr或者fetch设置断点的步骤很简单,在source面板的js调试窗口里面的XHR/fetch Breakpoints添加关键字就可以了,如下图所示: 如何添加XHR断点 举个例子,在掘金上给包含list的网络请求打个断点: image.png

Event listener

当你想要找出页面上某些元素绑定的事件的时候,可以使用事件监听断点,设置事件监听断点的位置如下: image.png 举个例子,如果想知道点击了掘金页面的“创作者中心”后触发的事件调用,可以参考如下操作: image.png 通过调试窗口的Call Stack可以查看调用栈情况,点击对应的文件进入即可查看目标按钮上绑定的点击事件代码。

Exception

当需要在抛出异常的代码行上暂停时,请使用异常断点。 先看默认情况下(未使用异常断点),下面代码的输出:

try {
  nonExistentFunction();
} catch (error) {
  console.log(error);
}
console.log('continue')
throw '未捕获的异常'
console.log('hello');

执行结果如下: 异常断点执行结果.png

点击JS调试窗口里最右侧的小按钮,可以设置异常断点,如下图所示: 设置异常断点.png 当小按钮变成蓝色的时候,表示异常按钮设置成功,此时执行上面的代码,程序进入断点暂停在未捕获的异常处,如果Pause on caught exceptions勾选上了,则异常不管有没有捕获,都会进入断点,如下: 异常断点.gif

Function

Console面板下的debug一样。

如何Debug

debug用到的几个按钮如下图所示(每个按钮都有对应的快捷键): debug.png

  1. Pause/Resume script execution: 暂停/恢复script执行
  2. Step over next function call:执行当前行
  3. Step into next function call:进入函数调用
  4. Step out of current function call:跳出当前函数
  5. step:按照时间顺序执行函数
  6. Deactivate breakpoints:禁用所有断点
  7. Do not pause on exceptions:异常处不暂停

下面可以用一段demo来了解下几个按钮的区别。

const a = 2
function add(b, c) {
  const num1 = Number(b)
  const num2 = Number(c)
  return num1 + num2
}

function addAll(b, c) {
  const d = 10
  result = add(b,c)
  setTimeout(() => {
    let a = 1
    alert('hahha')
    a = a + 1
  })
  return a + d + result
}

addAll(3, 6)

1、Step overstep into的区别:

如下图所示,当js执行到19行的时候,此时点击Step overstep into是没有区别的。 image.png 而当js执行到20行的时候,此时点击Step over会直接运行完add方法,停在20行;点击Step into则会进入add方法,停在13行。 image.png

2、Step into 与 Step 的区别: Step intoStep的区别主要是体现在异步上,如下图所示,当代码执行到21行的时候,此时点击step into,代码将按顺序执行22行。而点击step,代码将跳到26行执行。 image.png 如果是这样的话,那调整了执行顺序,是不是会导致不一样的结果?可以在26行加上consoel.log('hello')试一下~

当代码停在断点处时,我们可以进行如下图的操作: image.png

我们也可以点击Call Stack里面的函数切换当前的函数执行上下文。举个例子,js暂停在如下图所示的地方: image.png 此时点击Call Stack里面的addAll,可以看到如下图的变化: image.png

workspace

添加文件夹到workspace的位置如下图所示: image.png workspace就是一个编辑器,在workspace里面对文件进行的操作都会同步到磁盘上。只是输入提示不太友好,如果你喜欢纯手写代码的话,完全可以在workspace里面进行开发,避免在编辑器和chrome之间来回切换的麻烦。

workspace还有一个好处是可以帮助定位生产环境的bug。操作步骤如下: ①、将本地代码build之后生成的dist文件添加到workspace。然后找到你接下来要打断点的那个文件的map文件,右键,点击Copy link address,如下图所示: image.png 然后在page页面找到目标文件,在文件编辑窗口右键,点击Add source map,将刚才复制的文件链接添加进去,当你在目标文件打断点的时候,会跳转到刚添加的map文件的对应位置。此时就可以和本地debug一样了,不用耐着性子看压缩后的代码了。

overrides

当调试线上代码的时候,如果想让临时修改在刷新页面的时候不会被覆盖。则可以使用overridesoverrides的使用步骤如下:

  1. 首先添加一个文件夹用于保存修改后的文件
  2. page中找到目标文件进行修改后进行保存即可

此时再刷新页面,可以看到修改后的文件生效了,如下图所示: overrides.gif

此时查看overrides下的文件,可以看到修改后的文件: image.png 查看本地磁盘上的test文件夹也是同样的内容。

需要注意的是,修改完成之后,需要将Enable Local Overrides前面的勾去掉,否则每次打开该网页,都是加载的本地文件。

Content script

存放和chrome插件相关的代码。

Snippets

存放一些需要经常使用的js片段。使用方法如下: image.png

运行snippets的快捷方式,ctrl+p调出命令面板,输入!运行snippets文件名回车即可,如下: image.png