脱离996,Chrome DevTools 面板全攻略!!!

李华西,微医云服务团队前端开发工程师,喜欢瞎折腾,典型猫奴javascript

Console 面板

此章节请打开 devtools/console/console.html 一块儿食用css

一方面用来记录页面在执行过程当中的信息(通常经过各类 console 语句来实现),另外一方面用来当作 shell 窗口来执行脚本以及与页面文档、DevTools 等进行交互html

组合快捷键按键:
Windows: Control + Shift + J
Mac: Command + Option + J前端

首先看一下 console 对象下面都有哪些方法:
java

console.clear()

顾名思义,清空控制台node

console.log(), info(), warn(), error()

平常用的比较多的就是这几个了,其中 loginfo,印象中在 2016 年以前老用 info 打印,仍是有区别的,info 输出的内容前面是有一个蓝色背景的小圈, 大概跟这个差很少: i,后来 chrome 更新就没了 (IE 仍是能够看出差异的)webpack

console.log('普通讯息')
console.info('提示性信息')
console.error('错误信息')
console.warn('警示信息')
复制代码
复制代码

使用占位符git

// 支持逗号分隔参数,不须要每一个参数都单独打印
console.log(1, '2', +'3')
// 占位符
// %s 
console.log('今晚%s 老虎', '打', '???')
// %c 
console.log('今晚%s%c 老虎', '打', 'color: red', '???')
// 带有占位符的参数以后的若干参数属于占位符的配置参数
复制代码
复制代码

其他的占位符列表还有:github

占位符 功能
%s 字符串
%d 整数
%i 整数
%f 浮点数
%o 对象的连接
%c css 格式字符串

console.time(), timeEnd()

timetimeEnd 通常放在一块儿用,传入一个参数用来标识起始位置用于统计时间:web

console.time('t')
Array(900000).fill({}).forEach((v, index) => v.index = index)
console.timeEnd('t')
// t: 28.18603515625ms
复制代码
复制代码

会打印出中间代码的执行时间

console.count()

顾名思义。。计数, 能够用来统计某个函数的执行次数,也能够传入一个参数,而且根据传入的参数分组统计调用的次数

function foo(type = '') {
  type ? console.count(type) : console.count()
  return 'type:' + type
}

foo('A') //A: 1
foo('B') //B: 1
foo()    //default: 1
foo()    //default: 2
foo()    //default: 3
foo('A') //A: 2
复制代码
复制代码

console.trace()

用于追踪代码的调用栈,不用专门断点去看了

console.trace()
function foo() {
  console.trace()
}
foo()
复制代码
复制代码

console.table()

console.table() 方法能够将复合类型的数据转为表格显示

var arr = [
  { name: '梅西', qq: 10 },
  { name: 'C 罗', qq: 7 },
  { name: '内马尔', qq: 11 },
]
console.table(arr)
复制代码
复制代码

console.dir()

按便于阅读和打印的形式将对象打印

var obj = {
  name: 'justwe7',
  age: 26,
  fn: function () {
    alert('justwe7')
  },
}
console.log(obj)
console.dir(obj)
复制代码
复制代码

打印 DOM 对象区别:

console.assert()

断言,用来进行条件判断。当表达式为 false 时,则显示错误信息,不会中断程序执行。

能够用于提示用户,内部状态不正确(把那个说假话的揪出来)

var val = 1
console.assert(val === 1, '等于 1')
console.assert(val !== 1, '不等于 1')
console.log('代码往下执行呢啊')
复制代码
复制代码

console.group(), groupEnd()

分组输出信息,能够用鼠标折叠 / 展开

console.group('分组 1')
console.log('分组 1-1111')
console.log('分组 1-2222')
console.log('分组 1-3333')
console.groupEnd()
console.group('分组 2')
console.log('分组 2-1111')
console.log('分组 2-2222')
console.log('分组 2-3333')
console.groupEnd()
复制代码
复制代码

$ 选择器

$_

能够记录上次计算的结果,直接用于代码执行:

$0,$1...$4

表明最近 5 个审查元素选中过的 DOM 节点,看图(是要选中一下,我更喜欢用存储全局变量的方式玩,省的本身手残又选了一个节点):

$和?

  • $(selector)是原生 document.querySelector() 的封装。
  • ?(selector)返回的是全部知足选择条件的元素的一个集合,是 document.querySelectorAll() 的封装

$x

将所匹配的节点放在一个数组里返回

<ul>
  <ul>
    <li><p>li 下的 p1</p></li>
    <li><p>li 下的 p2</p></li>
    <li><p>li 下的 p3</p></li>
  </ul>
</ul>
<p>外面的 p</p>
复制代码
复制代码
$x('//li') // 全部的 li
$x('//p') // 全部的 p
$x('//li//p') // 全部的 li 下的 p
$x('//li[p]') // 全部的 li 下的 p
复制代码
复制代码

keys(), values()

跟 ES6 对象扩展方法, Object.keys()Object.values() 相同

keys(obj);
values(obj);
复制代码
复制代码

copy()

能够直接将变量复制到剪贴板

copy(temp1)
复制代码
复制代码

Save global variable 结合使用神器

Element 面板

此章节请打开 devtools/element/element.html 一块儿食用

在 Elements 面板中能够经过 DOM 树的形式查看全部页面元素,同时也能对这些页面元素进行所见即所得的编辑

组合快捷键按键:
Windows: Control + Shift + C
Mac: Command + Option + C

css 调试

style

选中目标节点,element 面版,查看 style->:hov, 选择对应的状态便可

computed

有时候样式覆盖过多,查看起来很麻烦,computed 就派上用场了

点击某个样式能够直接跳转至对应 css 定义

调整某个元素的数值

选中想要更改的值,按方向键上下就能够 + / - 1 个单位的值

alt + 方向键 能够 ×10 调整单位值
Ctrl + 方向键 能够 ×100 调整单位值
shift + 方向键 能够 /10 调整单位

html 调试

骚操做

选中节点,直接按键盘 H 能够直接让元素显示 / 隐藏,不用手动敲样式了,效果等同 visibility: hidden,仍是要占据盒模型空间的。(记得把输入法改为英文~)

将某个元素存储到全局临时变量中

选中节点,右键,Store as global variable(在 network 面板中也能用,尤为是筛选接口的返回值很方便)

滚动到某个节点

若是页面很长,想找一个文本节点的显示位置又不想手动滑动能够试试 Scroll into view

Edge 专属的 3D 视图

使用 chromium 后的 Edge 真的是改头换面,3D 视图能够帮忙定位一些定位层级还有 DOM 嵌套的问题,页面结构写的好很差看很直观的能够看出来 (跟辅助功能里面的 dom 树结合使用很舒服)

目前 chrome 仍是没有这项功能的,Edge 打开位置:控制台打开状态 => Esc打开抽屉 => ···选择 3D 视图面板

DOM 断点

能够监听到 DOM 节点的变动 (子节点变更 / 属性变动 / 元素移除),并断点至变动 DOM 状态的 js 代码行:

Network 面板

能够查看经过网络请求的资源的相关详细信息

组合快捷键按键:
Windows: Control + Shift + I
Mac: Command + Option + I

按区域划分大概分为以下几个区域:

  1. Controls - 控制 Network 功能选项,以及一些展现外观

  2. Filters - 控制在 Requests Table 中显示哪些类型的资源

    tips:按住 Cmd (Mac) 或 Ctrl (Windows/Linux) 并点击筛选项能够同时选择多个筛选项

  3. Overview - 此图表显示了资源检索时间的时间线。若是看到多条竖线堆叠在一块儿,则说明这些资源被同时检索

  4. Requests Table - 此表格列出了检索的每个资源。 默认状况下,此表格按时间顺序排序,最先的资源在顶部。点击资源的名称能够显示更多信息。 提示:右键点击 Timeline 之外的任何一个表格标题能够添加或移除信息列

  5. Summary - 能够一目了然地看到页面的请求总数、传输的数据总量、加载时间

(一、2)Controls,Filters 区域

Filters 控制的展现:

  • 使用大请求行 - 默认状况下,Requests Table一个资源只显示很小的一行。选中Use large resource rows(使用大资源行) 按钮能够显示两个文本字段:主要字段和次要字段。
  • 捕获屏幕截图 - 将鼠标悬停在某个屏幕截图上的时候,Timeline/Waterfall(时间轴) 会显示一条垂直的黄线,指示该帧是什么时候被捕获的
  • 显示概述 - 展现页面整个生命周期的各个阶段(Overview 区域)的耗时(蓝色绿色的那些横杠)

(3) Overview 区域

页面整个生命周期的各个阶段网络资源加载耗时信息的汇总,能够选择区域来筛选 Requests Table 的详细资源信息

(4) Requests Table 区域

标题栏的对应描述:

  • Name(名称): 资源的名称。
  • Status(状态): HTTP 状态代码。
  • Type(类型): 请求的资源的 MIME 类型。
  • Initiator(发起): 发起请求的对象或进程。它可能有如下几种值:
    • Parser(解析器): Chrome 的 HTML 解析器发起了请求。
    • Redirect(重定向): HTTP 重定向启动了请求。
    • Script(脚本): 脚本启动了请求。
    • Other(其余): 一些其余进程或动做发起请求,例如用户点击连接跳转到页面,或在地址栏中输入网址。
  • Size(大小): 响应头的大小(一般是几百字节)加上响应数据,由服务器提供。
  • Time(时间): 总持续时间,从请求的开始到接收响应中的最后一个字节
  • Timeline/Waterfall(时间轴): 显示全部网络请求的可视化统计信息

在标题栏如 (Name 上) 右键,能够添加或删除信息列。好比能够多加一列 Response Header => Content-Encoding 选项来总览页面资源的 gzip 压缩状况:

从新发起xhr请求

在平时和后端联调时,咱们用的最多的可能就是Network面板了。可是每次想从新查看一个请求经过刷新页面、点击按钮等方式去触发xhr请求,这种方式有时显得会比较麻烦,能够经过Replay XHR的方式去发起一条新的请求:

查看 HTTP 相关信息

查看网络请求的参数

能够经过点击 query string parameters (查询字符串参数) 旁边的 view URL encoded (查看 URL 编码) 或 view decoded (查看解码) 连接,查看 URL 编码或解码格式的 query string parameters (查询字符串参数)。在使用 postman 复制相关入参时尤为实用。

查看 HTTP 响应内容 点击 Response(响应) 标签页能够查看该资源未格式化的 HTTP 响应内容

接口的返回值 (在 preview 中)一样也能够 Save global variable 存储一个全局变量

Size 和 Time 为何有两行参数?

关于 Size 列

Size有两行:

  • 第一行表示的是数据的传输时的大小,例如上图中的190KB
  • 第二行表示的是数据实际的大小708KB

在服务器端采起gzip压缩算法将原有708KB压缩至190KB, 传输大小缩短3.7 倍,大大的提升了资源传输的效率

须要注意的点:

gzip压缩只会压缩响应体内容,因此适用于返回数据量大的时候,若是数据量过小的话,有可能会致使数据传输时的大小比实际大小要大 (加入了一些额外的响应头)

关于 Time 列

Time 有两行:

  • 第一行表示从客户端发送请求到服务端返回全部数据所花费的总时间,对于上图来讲就是471ms
  • 第二行表示的是从客户端发送请求到服务器端返回第一个字节所表示的时间,对于上图来讲就是55ms

第一行的时间表明了全部项目:例如解析 dns创建链接等待服务器返回数据传输数据

第二行的时间是 总时间 - 数据传输的时间

从上面的分析中咱们看到 从客户端请求到服务器处理结束准备返回数据花了55ms,可是在进行传输数据的时候花费了471ms

对于网慢的用户来讲,可能会耗费更长的时间,因此在写代码(接口)的时候,返回的数据量要尽可能精简

Waterfall

点击某个资源会展现出详细的网络加载信息:

相关字段描述:

  • Queuing (排队)

    浏览器在如下状况下对请求排队

    1. 存在更高优先级的请求, 请求被渲染引擎推迟,这常常发生在 images(图像)上, 由于它被认为比关键资源(如脚本 / 样式)的优先级低。
    2. 此源已打开六个 TCP 链接,达到限值,仅适用于 HTTP/1.0 和 HTTP/1.1。在等待一个即将被释放的不可用的 TCP socket
    3. 浏览器正在短暂分配磁盘缓存中的空间,生成磁盘缓存条目(一般很是快)
  • Stalled (停滞) - 发送请求以前等待的时间。它可能由于进入队列的任意缘由而被阻塞,这个时间包括代理协商的时间。请求可能会因 Queueing 中描述的任何缘由而中止。

  • DNS lookup (DNS 查找) - 浏览器正在解析请求 IP 地址,页面上的每一个新域都须要完整的往返 (roundtrip) 才能进行 DNS 查找

  • Proxy Negotiation - 浏览器正在与代理服务器协商请求

  • initial connection (初始链接) - 创建链接所需的时间,包括 TCP 握手 / 重试和协商 SSL。

  • SSL handshake (SSL 握手) - 完成 SSL 握手所用的时间

  • Request sent (请求发送) - 发出网络请求所花费的时间,一般是几分之一毫秒。

  • Waiting (等待) - 等待初始响应所花费的时间,也称为Time To First Byte(接收到第一个字节所花费的时间)。这个时间除了等待服务器传递响应所花费的时间以外,还包括 1 次往返延迟时间及服务器准备响应所用的时间(服务器发送数据的延迟时间)

  • Content Download(内容下载) - 接收响应数据所花费的时间 (从接收到第一个字节开始,到下载完最后一个字节结束)

  • ServiceWorker Preparation - 浏览器正在启动 Service Worker

  • Request to ServiceWorker - 正在将请求发送到 Service Worker

  • Receiving Push - 浏览器正在经过 HTTP/2 服务器推送接收此响应的数据

  • Reading Push - 浏览器正在读取以前收到的本地数据

(5) Summary 区域

requests 查看请求的总数量 | transferred 查看请求的总大小 | resources 资源 | Finish 全部 http 请求响应完成的时间 | DOMContentLoaded 时间 | load 时间

当页面的初始的标记被解析完时,会触发 DOMContentLoaded。 它在 Network(网络) 面板上的显示:

  • 在 Overview (概览) 窗格中的蓝色垂直线表示这个事件。
  • 在 Requests Table (请求列表) 中的红色垂直线也表示这个事件。
  • 在 Summary (概要) 窗格中,您能够查看事件的确切时间。

当页面彻底加载时触发 load 事件。 它显示也显示在:

  • 在 Overview (概览) 窗格的红色垂直线表示这个事件。
  • 在 Requests Table (请求列表) 中的红色垂直线也表示这个事件。
  • 在 Summary (概要) 中,能够查看改事件的确切时间

DOMContentLoaded 会比 Load 时间小,二者时间差大体等于外部资源加载(通常是图片 / 字体)的时间

Finish 时间是页面上全部 http 请求发送到响应完成的时间(若是页面存在一个轮询的接口,这个值也会累加的)。HTTP1.0/1.1 协议限定单个域名的请求并发量是 6 个,即 Finish 是全部请求(不仅是 XHR 请求,还包括 DOC,img,js,css 等资源的请求)在并发量为 6 的限制下完成的时间。

  • Finish 的时间比 Load 大,意味着页面有至关部分的请求量
  • Finish 的时间比 Load 小,意味着页面请求量不多,若是页面是只有一个 html 文档请求的静态页面,Finish 时间基本就等于 HTML 文档请求的时间

因此 Finish 时间与 DOMContentLoaded 和 Load 并没有直接关系

使用 Network 面板进行网络优化

参考 Network 面板能够针对 Network 提出一些优化建议

排队或中止阻塞

最多见的问题是不少个请求排队或被阻塞。这表示从单个客户端检索的资源太多。在 HTTP 1.0/1.1 链接协议中,Chrome 限制每一个域名最多执行 6 个 TCP 链接。若是一次请求十二个资源,前 6 个将开始,后 6 个将排队。一旦其中一个请求完成,队列中的第一个请求项目将开始其请求过程。

要解决传统 HTTP 1 的此问题,须要用多个子域名提供服务资源,将资源拆分到多个子域中,均匀分配。

上面说的修复 HTTP 1 链接数问题,不适用于 HTTP 2 链接,若是已部署 HTTP 2,不要对资源进行域划分,由于它会影响 HTTP 2 的工做原理(在 HTTP 2 中 TCP 链接多路复用链接的)。取消了 HTTP 1 的 6 个链接限制,而且能够经过单个链接同时传输多个资源。

接收到第一个字节的时间很慢

绿色的块占据比例很高:

TTFB 就是等待第一个响应字节的时间,建议在 200ms 如下,如下状况可能会致使高 TTFB:

  1. 客户端和服务器之间的网络条件差
  2. 要么,服务器端程序响应很慢

为了解决高 TTFB,首先去排除尽量多的网络链接。理想状况下,在本地托管应用程序(部署在本地),并查看是否仍有一个大的 TTFB。若是有,那么须要优化应用程序针的响应速度。这可能意味着优化数据库查询,为内容的某些部分实现高速缓存,或修改 Web 服务器配置。后端可能很慢的缘由有不少。您须要对您的程序进行研究,并找出不符合您预期的内容。

若是本地 TTFB 低,那么是您的客户端和服务器之间的网络问题。网络传输可能被不少种事情干扰阻碍。在客户端和服务器之间有不少点,每一个都有本身的链接限制,可能会致使问题。测试减小这种状况的最简单的方法是将您的应用程序放在另外一台主机上,看看 TTFB 是否改进。

加载缓慢

蓝色的块占据比例很高:

若是 Content Download (内容下载) 阶段花费了不少时间,提升服务响应速度、并行下载等优化措施帮助都不大。 主要的解决方案是发送更少的字节(好比一张高质量的大图可能几 M 的大小,这时能够酌情优化一下图片的宽高 / 清晰度)

Sources 面板

此章节请打开 /devtools/debug-js/get-started.html 一块儿食用

主要用来调试页面中的 JavaScript

自定义代码片断 Snippets

咱们常常有些 JavaScript 的代码想在控制台中调试,假如代码量多的状况下直接在 console 下写比较麻烦,或者咱们常常有些代码片断 (防抖、节流、获取地址栏参数等) 想保存起来,每次打开 Devtools 都能获取到这些代码片断,而不用再去从笔记里面找。

如图所示,在 Sources 这个tab栏下,有个 Snippets 标签,在里面能够添加一些经常使用的代码片断。(当个小笔记本)

设置断点

断点的面板

指定位置的中断

断点调试基本流程

找到源代码,点击要中断代码执行的位置,点击红色按钮的位置。而后再触发该方法执行,由于已知点击按钮能够触发,精准的定位到代码行就能够了:

全局事件中断

假如不知道代码执行的位置,如如下场景:

看接口返回的列表总数应该是 20 条,可是页面到 15 条就显示到底部了

看代码写的判断条件有点问题,但从编译后的代码找到对应位置进行调试就至关于大海捞针了。想试试本身的设想的解决方式是否正确:

  1. 由于列表是提拉加载,因此确定会触发网络请求,能够在事件侦听器里面打一个 XHR 的断点

  2. 而后提拉加载页面触发接口请求,如预期的,代码中断执行了。但提示找不到 sourcemap,暂时把 js 的资源映射给关掉 (相关解决方式)

  3. 再次触发断点,发现能够查看到中断的代码了,由于确定是页面中的业务代码将请求推入到执行堆栈的,因此能够在堆栈中找到对应的方法名:getVideoList

  4. 点击方法名能够跳转到对应的源码,能够看到圈起来的代码和所猜测的问题代码应该是同一处

  5. 回过来看下问题缘由: 页面请求完新数据后直接 pageNum 自增,而后直接就用因而否结束的判断了,有点不够严谨,不如直接比对当前的列表长度与接口返回的数据总数来判断:

  6. 记住要修改的代码,在这个文件开头,也就是 191.xxx.js

    1. 第一行先打个断点,push 方法以前再打一个断点: (若是没有再刷新一下 (也不清楚为何可能会没有))
    2. 而后刷新页面,找到刚刚想要修改的代码: 用 t.recommendList.length 替换掉 n.pageSize*t.pageNo(前两步是为了不 js 开始解析问题代码,先阻塞一下运行: stackoverflow
  7. Ctrl + S,保存一下,而后看下页面效果,列表能够所有加载出来了:

在美化代码的面板中是不支持直接修改页面代码的

黑盒模式

把脚本文件放入 Blackbox(黑盒),能够忽略来自第三方库的调用堆栈

默认(不开启黑盒):

开启黑盒:

  • 打开方式①

    1. 打开 DevTools Settings (设置)
    2. 在左侧的导航菜单中,单击 Blackboxing (黑箱)
    3. 点击 Add pattern... (添加模式) 按钮。
    4. Pattern(模式) 文本框输入您但愿从调用堆栈中排除的文件名模式。DevTools 会排除该模式匹配的任何脚本。
    5. 在文本字段右侧的下拉菜单中,选择 Blackbox (黑箱) 以执行脚本文件可是排除来自调用堆栈的调用,或选择 Disabled (禁用) 来阻止文件执行。
    6. 点击Add(添加) 保存
  • 打开方式②
    直接在想要忽略的堆栈信息上 blackbox script

DOM 断点

查看 element 面板 DOM 断点

Performance 面板

此章节请使用 Chrome 的隐身模式打开 /devtools/jank/index.html 一块儿食用 隐身模式能够保证 Chrome 在一个相对干净的环境下运行。假如安装了许多 chrome 插件,这些插件可能会影响分析性能表现

在 Performance 面板能够查看页面加载过程当中的详细信息,好比在什么时间开始作什么事情,耗时多久等等。相较于 Network 面板,不只能够看到经过网络加载资源的信息,还能看到解析 JS、计算样式、重绘等页面加载的方方面面的信息

面板主要的区域划分:

  1. Controls - 开始记录,中止记录和配置记录期间捕获的信息

  2. Overview - 页面性能的汇总

  3. Flame Chart - [火焰图 (线程面板)]。在火焰图上看到三条(绿色的有好几条)垂直的虚线:

    • 蓝线表明 DOMContentLoaded 事件
    • 绿线表明首次绘制的时间
    • 红线表明 load 事件
  4. Details - 在 Flame Chart 中,选择了某一事件后,这部分会展现与这个事件相关的更多信息;

    若是选择了某一帧,这部分会展现与选中帧相关的信息。若是既没有选中事件也没有选中帧,则这部分会展现当前记录时间段内的相关信息。

开始记录

  1. 首先点击控制条左边的第一个圆圈,开始记录日志
  2. 等待几分钟 (正常操做页面)
  3. 点击 Stop 按钮,Devtools 中止录制,处理数据,而后显示性能报告

而后就会出来上图的内容

与台式机和笔记本电脑相比移动设备的 CPU 功率要小得多。不管什么时候分析页面,都使用 CPU 限制来模拟页面在移动设备上的表现。 在 "开发工具" 中,单击 "性能" 选项卡。 确保启用 "屏幕截图" 复选框。 单击 "捕获设置"。 Capture SettingsDevTools 揭示了与如何捕获性能指标相关的设置。 对于 CPU,选择 2 倍减速。DevTools 会限制 CPU 使其速度比平时慢 2 倍

注意:若是想要确保它们在低端移动设备上运行良好,请将 CPU 限制设置为 20 倍减速。

(1)controls 控制条区域

  • 上半区域
    • Screenshots 截图:默认勾选,每一帧都会截图
    • Memory 内存消耗记录:勾选后能够看到各类内存消耗曲线
  • 下面的 checkbox 区域
    • Disable javaScript samples [禁用 javaScript 示例]:减小在手机运行时系统的开销,模拟手机运行时勾选
    • Network [网络模拟]:能够模拟在 3G,4G 等网络条件下运行页面
    • Enable advanced paint instrumentation(slow) [启用高级画图检测工具 (慢速)]:捕获高级画图检测工具,带来显著的性能开销
    • CPU [CPU 限制性能]:主要为了模拟底 CPU 下运行性能

(2)overview 总览区域

FPS

绿色竖线越高,FPS 越高。 FPS 图表上的红色块 (上图刚开始的部分) 表示长时间帧,极可能会出现卡顿。常常打游戏确定知道这个指标表明什么,120FPS 表明流畅(手动滑稽)

火焰图的 FPS 能够量化这项参数

FPS(frames per second)是用来分析动画的一个主要性能指标。能保持在 60 的 FPS 的话,那么用户体验就是不错的

Q: 为何是 60fps?

A: 咱们的目标是保证页面要有高于每秒 60fps(帧) 的刷新频率,这和目前大多数显示器的刷新率相吻合 (60Hz)。若是网页动画可以作到每秒 60 帧,就会跟显示器同步刷新,达到最佳的视觉效果。这意味着,一秒以内进行 60 次从新渲染,每次从新渲染的时间不能超过 16.66 毫秒

CPU

CPU 资源。此面积图指示消耗 CPU 资源的事件类型。在 CPU 图表中的各类颜色与 Summary 面板里的颜色是相互对应的,Summary 面板就在 Performance 面板的下方。CPU 图表中的各类颜色表明着在这个时间段内,CPU 在各类处理上所花费的时间。若是你看到了某个处理占用了大量的时间,那么这可能就是一个能够找到性能瓶颈的线索

CPU 资源面积图颜色划分:
颜色 执行内容
蓝色 (Loading) 网络通讯和 HTML 解析
黄色 (Scripting) JavaScript 执行
紫色 (Rendering) 样式计算和布局,即重排
绿色 (Painting) 更改外观而不会影响布局,重绘
灰色 (other) 其它事件花费的时间
白色 (Idle) 空闲时间

重绘是当节点须要更改外观而不会影响布局的,好比改变 color 就叫称为重绘 回流 (重排) 是布局或者几何属性须要改变就称为回流

重排一定会发生重绘,重绘不必定会引起重排。重排所需的成本比重绘高的多,改变深层次的节点极可能致使父节点的一系列重排

js 修改 dom 结构或样式 -> 计算 style -> layout(重排) -> paint(重绘) -> composite(合成)

性能优化的相关总结

NET

每条彩色横杠表示一种资源。横杠越长,检索资源所需的时间越长。 每一个横杠的浅色部分表示等待时间(从请求资源到第一个字节下载完成的时间) 深色部分表示传输时间(下载第一个和最后一个字节之间的时间)

  • HTML:蓝色
  • CSS:紫色
  • JS:黄色
  • 图片:绿色

感受优化网络性能直接使用 network 面板就行了

(3)Flame Chart 火焰图(线程面板)

详细的分析某些任务的详细耗时,从而定位问题

看到的几条虚线:

  • 蓝线表明 DOMContentLoaded 事件
  • 绿线表明首次绘制的时间
    • FP(First Paint): 首次绘制
    • FCP(First Contentful Paint): 第一次丰富内容的绘图
    • FMP(First Meaningful Paint):第一次有意义的绘图
    • LCP(Largest Contentful Paint): 最大区域内容绘制
  • 红线表明 load 事件
  • DOMContentLoaded: 就是 dom 内容加载完毕。 那什么是 dom 内容加载完毕呢?打开一个网页当输入一个 URL,页面的展现首先是空白的,而后过一会,页面会展现出内容,可是页面的有些资源好比说图片资源还没法看到,此时页面是能够正常的交互,过一段时间后,图片才完成显示在页面。从页面空白到展现出页面内容,会触发 DOMContentLoaded 事件。而这段时间就是 HTML 文档被加载和解析完成。

  • load: 页面上全部的资源(图片,音频,视频等)被加载之后才会触发 load 事件,简单来讲,页面的 load 事件会在 DOMContentLoaded 被触发以后才触发。

Main

看下主线程,Devtools 展现了主线程运行情况

  • X 轴表明着时间。每一个长条表明着一个 event。长条越长就表明这个 event 花费的时间越长。
  • Y 轴表明了调用栈(call stack)。在栈里,上面的 event 调用了下面的 event

Google 官方文档的例子:

如上图:click 事件触发了 script_foot_closure.js 第 53 行的函数调用。 再看下面,Function Call 能够看到一个匿名函数被调用,而后调用 Me() 函数,而后调用 Se(),依此类推。

DevTools 为脚本分配随机颜色。在上图中,来自一个脚本的函数调用显示为浅绿色。来自另外一个脚本的调用被渲染成米色。较深的黄色表示脚本活动,而紫色的事件表示渲染活动。这些较暗的黄色和紫色事件在全部记录中都是一致的。

  1. 在性能报告中,有不少的数据。能够经过双击,拖动等等动做来放大缩小报告范围,从各类时间段来观察分析报告
  2. 在事件长条的右上角处,若是出现了红色小三角,说明这个事件是存在问题的,须要特别注意
  3. 双击这个带有红色小三角的事件。在 Summary 面板会看到详细信息。注意 reveal 这个连接,双击它会让高亮触发这个事件的 event。若是点击了 app.js:94 这个连接,就会跳转到对应的代码处

(4)Details 区域

通常要配合 Flame Chart 一块儿使用

  • Summary 区域是一个饼状图总览,汇总了各个事件类型所耗费的总时长,另外还有三个查看选项:
  • Bottom-Up 选项卡:要查看直接花费最多时间的活动时使用
  • Call Tree 选项卡:想查看致使最多工做的根活动时使用
  • Event Log 选项卡:想要按记录期间的活动顺序查看活动时使用

window.performance 对象

Performance 接口能够获取到当前页面中与性能相关的信息。它是 High Resolution Time API 的一部分,同时也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。

实质上来讲 performance 对象就是专门用于性能监测的对象,内置了几乎全部经常使用前端须要的性能参数监控

performance API

performance API

  • memory

    • totalJSHeapSize: '可以使用内存大小' // 单位 KB
    • usedJSHeapSize: '已使用内存大小'
    • jsHeapSizeLimit: '内存大小限制'
  • navigation

    • redirectCount: 0

      若是有重定向的话,页面经过几回重定向跳转而来

    • type: 0

      相似于小程序定义的场景值,type 的值: 0 即 TYPE_NAVIGATENEXT 正常进入页面(非刷新、非重定向等) 1 即 TYPE_RELOAD 经过 window.location.reload() 刷新的页面 2 即 TYPE_BACK_FORWARD 经过浏览器的前进后退按钮进入的页面(历史记录) 255 即 TYPE_UNDEFINED 非以上方式进入的页面

  • onresourcetimingbufferfull // 一个当 resourcetimingbufferfull 事件触发时调用的 EventHandler 这个事件当浏览器的资源时间性能缓冲区已满时会触发

    // 在 onresourcetimingbufferfull 属性上设置一个回调函数:
    function buffer_full(event) {
      console.log("WARNING: Resource Timing Buffer is FULL!");
      performance.setResourceTimingBufferSize(200);
    }
    function init() {
      // Set a callback if the resource buffer becomes filled
      performance.onresourcetimingbufferfull = buffer_full;
    }
    <body onload="init()">
    复制代码
    复制代码
  • timeOrigin: 1594219100175.9412

    返回性能测量开始时的时间的高精度时间戳

  • timing

    • navigationStart: '时间戳'

      在同一个浏览器上下文中,前一个网页(与当前页面不必定同域)unload 的时间戳,若是无前一个网页 unload,则与 fetchStart 值相等;

    • unloadEventStart: 0

      前一个网页(与当前页面同域)unload 的时间戳,若是无前一个网页 unload 或者前一个网页与当前页面不一样域,则值为 0

    • unloadEventEnd: 0

      和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行王弼的时间戳

    • redirectStart: 0

      第一个 HTTP 重定向发生时的时间,有跳转且是同域名内部的重定向才算,不然值为 0

    • redirectEnd: 0

      最后一个 HTTP 重定向完成时的时间,有跳转切尔是同域名内部的重定向才算,不然值为 0

    • fetchStart: '时间戳'

      浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存以前

    • domainLookupStart: '时间戳'

      DNS 域名查询开始的时间,若是使用了本地缓存(即无 DNS 查询)或持久链接,则与 fetchStart 值相等

    • domainLookupEnd: '时间戳'

      DNS 域名查询完成的时间,若是使用了本地缓存(即 无 DNS 查询)或持久链接,则与 fetchStart 值相等

    • connectStart: '时间戳'

      HTTP(TCP) 开始创建链接的时间,若是是持久链接,则与 fetchStart 值相等;若是在传输层发生了错误且从新创建了链接,则这里显示的是新创建链接的时间

    • connectEnd: '时间戳'

      HTTP(TCP) 完成创建链接的时间(握手),若是是持久链接,则与 fetchStart 相等;若是是在传输层发生了错误且从新创建链接,则这里咸宁市的是新创建的链接完成的时间;这

    • secureConnectionStart: 0

      HTTPS 链接开始的时间,若是不是安全链接,则值为 0;

    • requestStart: '时间戳'

      HTTP 请求读取真实文档开始的时间(完成创建链接),包括从本地读取缓存,链接错误时这里显示的是新创建的链接的时间

    • responseStart: '时间戳'

      HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存

    • responseEnd: 0

      HTTP 响应所有接收完毕的时间(获取到最后一个字节),包括从本地读取的缓存

    • domLoading: 0

      开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件(这里只是 DOM 树解析完毕,这时候并无开始加载网页内的

    • dominteractive: 0

      完成解析 DOM 树的时间,Document,readyState 变为 interactive, 并将抛出 readystatechange 相关事件(这时候并无开始加载网页资源)

    • domContentLoadedEventStart: 0

      DOM 解析完成后,网页内资源加载开始的时间,在 DOMContentLoaded 事件抛出以前发生

    • domContentLoadedEventEnd: 0

      DOM 解析完成后,网页内资源加载完成的时间

    • domComplete: 0

      DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete, 并将抛出 readystatechange 相关事件

    • loadEventStart: 0

      load 事件发送给文档,也即 load 回调函数开始执行的时间,若是没有绑定 load 事件,值为 0

    • loadEventEnd: 0

      load 事件的回调函数执行完毕的时间

几个实用的 API

performance.now() 方法

performance.now() 返回 performance.navigationStart 至当前的毫秒数。 performance.navigationStart 是下文将介绍到的能够说是浏览器访问最初的时间测量点。

值得注意的两点:

  • 测量初始点是浏览器访问最初测量点,或者理解为在地址栏输入 URL 后按回车的那一瞬间。
  • 返回值是毫秒数,但带有精准的多位小数。

用 performance.now() 检测 js 代码的执行时间 (毫秒):

var st = performance.now();
  console.log(Array(9999999).fill(null).filter(v => !v).length);
  var end = performance.now();
  console.log(`取值时间${end - st}ms`); // 取值时间 558.7849999992759ms
复制代码
复制代码

performance.navigation

performance.navigation 负责纪录用户行为信息,只有两个属性:

  • redirectCount
    • 若是有重定向的话,页面经过几回重定向跳转而来
  • type
    • type 的值:
    • 0 即 TYPE_NAVIGATENEXT 正常进入页面(非刷新、非重定向等)
    • 1 即 TYPE_RELOAD 经过 window.location.reload() 刷新的页面
    • 2 即 TYPE_BACK_FORWARD 经过浏览器的前进后退按钮进入的页面(历史记录)
    • 255 即 TYPE_UNDEFINED 非以上方式进入的页面
console.log(performance.navigation); // PerformanceNavigation {type: 1, redirectCount: 0}
复制代码
复制代码
performance.timing

timing 内包含了几乎全部时序的时间节点

能够经过此字段来统计页面相关事件的发生时长:

function getTiming() {
  try {
    var timing = performance.timing;
    var timingObj = {};

    var loadTime = (timing.loadEventEnd - timing.loadEventStart) / 1000;

    if(loadTime < 0) {
      setTimeout(function() {
        getTiming();
      }, 0);
      return;
    }

    timingObj['重定向时间'] = (timing.redirectEnd - timing.redirectStart);
    timingObj['DNS 解析时间'] = (timing.domainLookupEnd - timing.domainLookupStart);
    timingObj['TCP 完成握手时间'] = (timing.connectEnd - timing.connectStart);
    timingObj['HTTP 请求响应完成时间'] = (timing.responseEnd - timing.requestStart);
    timingObj['DOM 开始加载前所花费时间'] = (timing.responseEnd - timing.navigationStart);
    timingObj['DOM 加载完成时间'] = ((timing.domComplete || timing.domLoading) - timing.domLoading);
    timingObj['DOM 结构解析完成时间'] = (timing.domInteractive - timing.domLoading);
    timingObj['整体网络交互耗时,即开始跳转到服务器资源下载完成时间'] = (timing.responseEnd - timing.navigationStart);
    timingObj['可交互的时间'] = (timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart);
    timingObj['首次出现内容'] = (timing.domLoading - timing.navigationStart);
    timingObj['onload 事件时间'] = (timing.loadEventEnd - timing.loadEventStart);
    timingObj['页面彻底加载时间'] = (timingObj['重定向时间'] + timingObj['DNS 解析时间'] + timingObj['TCP 完成握手时间'] + timingObj['HTTP 请求响应完成时间'] + timingObj['DOM 结构解析完成时间'] + timingObj['DOM 加载完成时间']);

    for(item in timingObj) {
      console.log(item + ":" + timingObj[item] + '(ms)');
    }

    console.log(performance.timing);

  } catch(e) {
    console.log(performance.timing);
  }
}
window.onload = getTiming
复制代码
复制代码
performance.memory

用于显示当前的内存占用状况

console.log(performance.memory)
/* {
  jsHeapSizeLimit: 4294705152,
  totalJSHeapSize: 13841857,
  usedJSHeapSize: 12417637
} */
复制代码
复制代码
  • usedJSHeapSize 表示:JS 对象(包括 V8 引擎内部对象)占用的内存数
  • totalJSHeapSize 表示:可以使用的内存
  • jsHeapSizeLimit 表示:内存大小限制

一般,usedJSHeapSize 不能大于 totalJSHeapSize,若是大于,有可能出现了内存泄漏。

performance.getEntries()

浏览器获取网页时,会对网页中每个对象(脚本文件、样式表、图片文件等等)发出一个 HTTP 请求。performance.getEntries 方法以数组形式,返回一个 PerformanceEntry 列表,这些请求的时间统计信息,有多少个请求,返回数组就会有多少个成员

  • name:资源的连接
  • duration: 资源的总耗时(包括等待时长,请求时长,响应时长 至关于 responseEnd - startTime)
  • entryType: 资源类型,entryType 类型不一样数组中的对象结构也不一样:
    该类型对象 描述
    mark PerformanceMark 经过 mark() 方法添加到数组中的对象
    measure PerformanceMeasure 经过 measure() 方法添加到数组中的对象
    paint PerformancePaintTiming 值为 first-paint'首次绘制、'first-contentful-paint'首次内容绘制。
    resource PerformanceResourceTiming 全部资源加载时间,用处最多
    navigation PerformanceNavigationTiming 现除 chrome 和 Opera 外均不支持,导航相关信息
    frame PerformanceFrameTiming 现浏览器均未支持
  • initiatorType: 如何发起的请求, 初始类型(注意这个类型并不许确,例如在 css 中的图片资源会这个值显示 css,因此仍是推荐用 name 中的后缀名)
    发起对象 描述
    a Element link/script/img/iframe 等 经过标签形式加载的资源,值是该节点名的小写形式
    a CSS resource css 经过 css 样式加载的资源,好比 background 的 url 方式加载资源
    a XMLHttpRequest object xmlhttprequest/fetch 经过 xhr 加载的资源
    a PerformanceNavigationTiming object navigation 当对象是 PerformanceNavigationTiming 时返回
performance.getEntriesByType()

方法返回给定类型的 getEntries 列表 打开页面

这段代码能够在 DevTools 控制台中运行。它将使用Resource Timing API(资源时序 API) 来检索全部资源。而后它过滤条目,查找包含logo-1024px.png名称的条目。若是找到,会返回相关信息。

performance
  .getEntriesByType('resource')
  .filter(item => item.name.includes('logo-1024px.png'))
复制代码
复制代码

注意:
返回资源的 connectEnd 等相关字段不是 Unix 时间戳,而是 DOMHighResTimeStampMDN PerformanceResourceTiming

DOMHighResTimeStamp 是一个 double 类型,用于存储时间值。该值能够是离散的时间点或两个离散时间点之间的时间差。T 单位为毫秒 ms (milliseconds) ,应准确至 5 微秒 µs (microseconds)。可是,若是浏览器没法提供准确到 5 微秒的时间值 (例如, 因为硬件或软件的限制), 浏览器能够以毫秒为单位的精确到毫秒的时间表示该值

Lighthouse(Audits) 面板

来自 Google 的描述: Lighthouse 是一个开源的自动化工具,用于改进网络应用的质量。 您能够将其做为一个 Chrome 扩展程序运行,或从命令行运行。 您为 Lighthouse 提供一个您要审查的网址,它将针对此页面运行一连串的测试,而后生成一个有关页面性能的报告

会对页面的加载进行分析,而后给出提升页面性能的建议

懒人专用👍

有 5 个指标:

  • Performance 性能
  • accessibility 无障碍使用
  • Best Practice 用户体验
  • SEO SEO 优化
  • Progressive Web App 页对于 PWA 的兼容性

Security 面板

用于检测当面页面的安全性

该面板能够区分两种类型的不安全的页面:

  • 若是被请求的页面经过 HTTP 提供服务,那么这个主源就会被标记为不安全。
  • 若是被请求的页面是经过 HTTPS 获取的,但这个页面接着经过 HTTP 继续从其余来源检索内容,那么这个页面仍然被标记为不安全。这就是所谓的混合内容页面, 混合内容页面只是部分受到保护, 由于 HTTP 内容 (非加密的内容通讯使用明文) 可能会被窃听, 容易受到中间人攻击。如 163,虽然证书是有效的,可是页面有一部分 http 资源:

Command 终极大招

在控制台打开的状态下, 组合按键 Ctrl + Shift + P / Command + Shift + P 打开 “命令” 菜单,接下来就能够随心所欲了~

截图

当你只想对一个特定的 DOM 节点进行截图时,可能须要使用其余工具操做很久,使用控制台能够直接选中想要截图的节点,打开 Command 菜单而且使用 节点截图 就能够了

  • 截取特定节点: Screenshot Capture node screenshot
  • 全屏截图: Screenshot Capture full size screenshot

CSS/JS 覆盖率

媒体查询

媒体查询是自适应网页设计的基本部分。 在 Chrome Devtools 中的设备模式下,在三圆点菜单点击, Show Media queries 便可启用:

右键点击某个条形,查看媒体查询在 CSS 中何处定义并跳到源代码中的定义

参考

相关文章
相关标签/搜索