Network
面板的作用是在devTools
打开的时候记录网络活动。如下图所示,Network
面板可以分为七个部分:
- 控制器
- 过滤器
- 设置
- 抓图信息
- 时间线
- 资源请求列表
- 资源请求信息概要
控制器
录制/停止网络活动日志
点击实心圆点小图标可以录制/停止录制网络活动日志
清除网络活动日志
点击禁止小图标可以清除当前的网络活动日志
控制过滤器显隐
点击漏斗小图标可以控制下面过滤器的显隐
查询
当你需要在所有的网络请求的HTTP
头部和响应体中查找某个关键字或者正则的时候,可以点击放大镜打开Search
面板(会出现在左侧)。
举个例子,我想查询下掘金前端推荐页面中的第一篇文章是哪个接口返回的,那么可以在Search
面板的搜索框中输入这篇文章的关键字,比如标题。如下图所示:
保留日志
当勾选了Preserve log
,刷新当前页面或者跨页面请求,依然会保留之前的网络请求日志。
禁用/启用缓存
勾选/取消Disable cache
,可以禁用/启用浏览器缓存,模拟用户初次使用站点的情况。
如下图所示,当没有勾选Disable cache
的时候,刷新掘金首页,可以看到79bfdb8.js
资源来自浏览器缓存。
当勾选了Disable cache
的时候,再次刷新页面,可以看到请求头中加入了cache-control: no-cache
,然后请求的服务器最新资源。
当勾选了Disable cache
的时候,有时候可以看到一些资源还是来自memory cache
,如下图所示:
什么原因?
观察上图可以看到来自memory cache
的资源都是base 64
格式的图片。这样就可以理解了,因为base 64
格式的图片是会跟着引用它的js
或者css
一起加载到浏览器的,所以当浏览器解析到当前需要的base 64
图片的时候,自然可以在缓存中找到它。
节流设置
点击No throtting
可以设置不同的节流模式,如果预置的节流模式不能满足需求,可以添加自定义设置。
网络状况设置
网络状况设置里面除了可以设置是否禁用缓存和网络节流模式外,还可以设置用户代理设置和http
请求头的Content-Encoding
。
设置用户代理
不使用浏览器默认设置之后,可以选择自定义的User Agent
。然后在http
请求头中可以看到User-Agent
等于自定义的值。如下图所示:
在console
中输入window.navigator.userAgent
也可以看到自定义的User Agent
。
当需要用window.navigator.userAgent
来判断浏览器信息的时候,可以通过在浏览器设置user agent
来辅助开发。
设置Content-Encoding
http
请求头中的Accept-Encoding
和响应头中的Content-Encoding
是一对用于协商采用何种压缩算法传输资源的字段,如下图所示:
发起请求的时候,浏览器先在请求头中带上Accept-Encoding: gzip, deflate
告诉服务器我能接收的压缩算法是gzip
和deflate
。然后服务器接收到该请求之后会在其中选择一个自己支持的压缩算法压缩资源并且在响应头中带上Content-Encoding: gzip
来告诉浏览器请求的内容是用gzip
压缩算法压缩的。
当浏览器和服务器的协商过程如上所述,且服务器上的vendor.js
的资源大小如下所示(约2M)的时候:
我们可以看到资源请求列表中vendor.js
的请求信息:
vendor.js
的原文件大小是2M
,然后压缩过后的大小是627k
。
还有两种特殊情况:
-
协商失败
比如请求头的
Accept-Encoding
是br
,然后服务端支持的压缩算法是gzip
,此时就是协商失败,那么这种情况下直接传输原文件。 -
协商成功也不压缩文件
即使浏览器和服务器都支持相同的压缩算法,服务器也可能不压缩发送的内容,原因就是内容已经是被压缩过的,再次压缩可能不会导致内容变小。
导出导入HAR file
HAR
(Http Archive
)是一个json
格式的文档,记录了浏览器和服务器交互的网络日志,扩展名是.har
。下图是一个完整的HAR
。entries
是一个数组,其中的每个元素就是一个网络请求。
当客户的生产环境定位bug
需要查看资源请求的时候,可以让客户点击HAR
导出的图标导出一份HAR
文件,然后开发人员可以将HAR
文件任意导入一个页面查看网络请求情况,如下图所示,我将掘金页面的部分网络请求导入了我已经打开的百度页面中查看。
过滤器
按文本过滤
在输入框中输入关键字可以对资源请求列表进行过滤
按正则过滤
如下图所示,过滤以svg
结尾的资源:
按属性过滤
在输入框中输入method:GET
可以过滤得到当前页面的所有的GET
请求,如下图所示:
那么怎么知道这里支持哪些属性过滤呢?输入-
则可以看到所有支持过滤的属性。
如果需要一次过滤多个条件,那么中间用空格隔开即可,比如method:GET domain:*.juejin.com
即可。
下表列出了这些属性代表的含义:
属性 | 释义 | 举例 |
---|---|---|
domain |
只显示来自指定域的资源 | domain:*.juejin.com :只显示来自juejin.com 结尾的域名的资源请求 |
has-response-header |
显示包含指定HTTP 响应标头的资源 |
has-response-header:age : 只显示响应头部有age 属性的资源请求 |
is |
显示指定来源的资源 | is:from-cache : 查找出从缓存中读出的资源 |
larger-than |
显示大于指定大小的资源(以字节为单位) | larger-than:10 : 只显示大于10B 的资源请求(默认单位是B ,也可以输入1k , 1M ) |
method |
显示通过指定HTTP 方法类型检索的资源 |
method:GET :只显示GET 请求 |
mime-type |
显示指定MIME 类型的资源 |
mime-type:text/javascript : 只显示响应头中Content-Type: text/javascript 的资源 |
mixed-content |
显示混合内容资源 | mixed-content:all : 显示所有混合内容 |
priority |
显示优先级与指定值匹配的资源 | priority:Highest : 只显示最高优先级的资源(devTools 将网络资源分成五个等级,分别是Lowest 、Low 、Medium 、High 、Highest ) |
scheme |
过滤http 或者https 资源 |
schema: http : 显示http 请求 |
set-cookie-domain |
显示具有与指定值匹配的属性的Set-Cookie 标头的资源 |
set-cookie-domain:api.juejin.cn : 显示响应头中设置了set-cookie 且cookie 的domain 等于api.juejin.cn 的资源 |
set-cookie-name |
显示具有Set-Cookie 名称与指定值匹配的标头的资源 |
set-cookie-name:ttcid : 显示响应头中的set-cookie 的name 等于ttcid 的资源 |
set-cookie-value |
显示具有Set-Cookie 值与指定值匹配的标头的资源 |
set-cookie-value:1234567 : 显示响应头中的set-cookie 的值等于1234567 的资源 |
resource-type |
显示资源类型的资源 | resource-type:script : 显示所有的js 资源 |
cookie-domain |
显示设置特定cookie 域的资源 |
cookie-domain:juejin.cn : 显示请求头中cookie 的domain 等于juejin.cn 的资源 |
cookie-name |
显示设置特定cookie 名称的资源 |
cookie-name:sid_tt : 显示请求头中cookie 有个name 等于sid_tt 的资源 |
cookie-path |
显示设置特定cookie 路径的资源 |
cookie-path:/kcs : 显示cookie 的path 等于/kcs 的资源 |
cookie-value |
显示设置特定cookie 值的资源 |
cookie-value:1234567 : 显示cookie 的值等于1234567 的资源 |
status-code |
仅显示其HTTP 状态代码与指定代码匹配的资源 |
status-code:200 : 显示状态码等于200 的资源 |
url |
显示具有url 匹配指定值的资源 |
url:https://api.juejin.cn/user_api/v1 : 显示来自url:https://api.juejin.cn/user_api/v1 的资源 |
反向过滤
反向过滤用-
即可。比如-js
就是过滤出所有不包含js
字符串的资源;再比如-status-code:200
可以过滤出资源列表中status code
不等于200
的请求。
隐藏数据URLs
数据URL
是指嵌入到其它文档中的小型文件。在资源请求表中以data:
开头的资源。比如js
中包含的base64
图片。
如下图所示,如果勾选上Hide data URLs
可以过滤掉图中框出的那条base64
图片的加载信息。
按资源类型过滤
点击All
、Fetch/XHR
等类型可以过滤对应类型的网络请求。如果需要多选,则ctrl
+鼠标左键即可。
已拦截的cookie
has blocked cookies
勾选该选项,可以过滤出响应cookie
被拦截的请求。
PS
:想模拟出has blocked cookies
勾选过滤出请求的场景,但是没成功…
如下图所示,在响应头部设置了一个非法的cookie
。将鼠标移到图中的黄色感叹号上显示:This attempt to set a cookie via a Set-Cookie header was blocked because its domain attribute was invalid with regards to the current host url
。但是勾选has blocked cookies
过滤不出该请求。
被屏蔽的请求blocked Requests
勾选该选项,可以过滤出被拦截的请求。被拦截的请求可能有如下几个原因:
blocked:devtools
触发了用户在devtools
的Network request blocking
中设置的拦截规则。
console
下的报错信息如下:
blocked:csp
触发了chrome
的内容安全策略检查CSP
。比如我在html
中加了一个meta
: <meta http-equiv="Content-Security-Policy" content="img-src 'self';">
,然后某个img
的src
是其它域下的,那么可以在network
下看到这个被拦截的请求
console
下的报错信息如下:
blocked:mixed-content
mixed-content
指的是在https
的网站里面加载http
协议的资源。比如本地启动了一个https
的服务,然后在html
里面增加一行<script src="http://172.25.1.74:7618/js/vendor.906956c9.js"></script>
,刷新页面,可以看到被拦截的请求:
console
下的报错信息如下:
设置
点击控制器最右侧的齿轮可以控制控制器的显隐,如下图所示:
Use large request rows
使用大请求行
默认情况下,资源请求列表中一个资源请求只显示很小的一行,如下图所示:
如果勾选Use large request rows
可以让一行占有更多的位置,且某些列还会提供更多的信息,如下图所示:
可以看到Size
和Time
有两个数据。
其中Size
第一个数据表示数据传输时(被压缩)的大小,第二个数据表示数据实际的大小。
需要注意的是实际大小不一定大于传输时的大小,这是因为压缩只会压缩响应体的大小,如果响应体的数据量太小,压缩时额外增加的一些响应头可能会导致传输时的数据比实际的数据大。
Time
的第一个值是从客户端发送请求到服务器端返回所有数据所花费的总时间。而第二个值则是从客户端发送请求到服务器返回第一个字节所花费的时间。
Group by frame
按frame
分组
勾选了Group by frame
则会将来自同个frame
的网络请求收集在一起。
Show overview
显示概览
勾选/取消Show overview
,则显示/隐藏概览窗口,如下图所示:
在概览窗口上单击然后向左/右拖动来过滤这段时间范围内的网络请求,如下图所示:
Capture screenshots
捕获屏幕截图
勾选了Capture screenshots
后重现加载页面可以捕获屏幕截图。如下图所示,选中其中一个截图,可以看到概览页面出现一条黄线,表示捕获到该屏幕截图的时间点。如下图所示:
双击缩略图可以放大该屏幕截图,如下图所示:
时间线
概览窗口通过动态的时间轴来记录目前所有的网络请求。其中花花绿绿的各种横线表示的是一个个的HTTP
请求,各种颜色代表的阶段如下图所示:
各个阶段介绍如下:
-
排队
Queueing
请求被添加到队列中并等待浏览器发送的时间间隔,排队的原因如下:
①有更高优先级的请求
②
chrome
中限制HTTP/1.0
和HTTP/1.1
只能为一个域名打开六个TCP
连接③浏览器正在磁盘缓存中短暂分配空间
-
阻塞
Stalled
请求出队列到请求真正发出的时间间隔,比如等待已建立的
TCP
链接被重新利用的时间。 -
初始化连接
Initial Connnection
浏览器建立连接,包括
TCP
三次握手等 -
SSL
完成
SSL
握手的时间 -
发送请求
Request Send
-
等待
TTFB``Waiting(TTFB/Time To First Byte)
浏览器等待响应的第一个字节,该时间=请求到达服务器的时间+服务器处理请求准备响应的时间+响应到达浏览器的时间
-
内容下载
Content Download
, 浏览器接受响应的时间
以上几个是一个HTTP
请求的构成阶段的一个子集,比如如果浏览器没有找到DNS
缓存的话,那么初始化连接之前还需要DNS
寻址。完整的HTTP
构成阶段可以参考 HTTP请求时间分解
详细信息
Requests
表记录了DevTools
打开后所有发送的请求。单击其中的某一个可以查看该请求的详细信息。
配置Request
表格的列
Request
表格的列是支持自定义配置的,支持配置的列如下图所示:
表格中大部分列代表什么意思都是浅显易懂的,下面简单介绍下平时开发中关注度没那么高的几列。
Remote address Space
在中文版本的chrome
中该字段翻译成”远程地址空间”,感觉不是很好理解,其实看下面三张图片就明白这个字段是什么意思了。
Initiator
可以查看触发该网络请求的对象或进程,它可能有以下几种值:
- 解析器
phase
:Chrome
的HTML
解析器发起了请求 - 重定向
Redirect
:HTTP
重定向启动了请求 - 脚本
Script
:脚本启动了请求 - 其他
Other
: 一些其他进程或动作发起了请求,例如用户点击链接跳转到页面或者在地址栏中输入网址
将鼠标移到当前列的initiator
可以看到如下图所示的调用栈信息,如下图所示:
Priority
代表请求资源的加载优先级,优先级一共有五种,从高到低分别是Highest
、High
、Medium
、Low
和Lowest
。
- 首先
chrome
将每种资源都设置了一个默认优先级,常见资源的优先级如下所示:
优先级 | 资源类型 |
---|---|
Highest |
html 、css 、font |
High |
script 、ajax |
Medium |
mainfest |
Low |
image |
Lowest |
prefetch |
- 针对一些特殊情况,
chorme
会动态调整资源加载的优先级,比如script
的默认的优先级是high
,但是如果给一个script
加上了defer
的话,那该script
的优先级会降低到Low
。
Connection ID
一个连接ID
代表一个TCP
连接。
没有找到直接的证据证明一个连接ID
代表一个TCP
。但是可以从下面的证据间接证明。
-
证据一
预备知识:可以通过
netstat -ant -p TCP
查看tcp
的连接情况。首先我们刷新掘金首页,过滤
domain=api.juejin.cn
的所有的http
请求,如下图所示:
可以看到Connection ID
一共有两个。
然后随便点开其中一个http
请求可以看到当时这个域名下的请求分发到了113.105.168.241
上,在Git Bash
中执行netstat -ant -p TCP | grep "113.105.168.241"
,可以看到:
多次测试可以看到Connection ID
的个数等于过滤出的TCP
的个数。
- 证据二
可以看下下面两张图,分别是http1.1
和http2
下的网络请求的Connecttion ID
根据我们已知的http
的相关知识:http1.1
中的一个tcp
可以传输多个http
请求。而http2
中一个域名只使用一个TCP
连接来传输多个http
请求。是不是也可以从侧面证明一个Connection ID
代表了一个TCP
连接。
现在来分析一个场景:新开一个tab
页,然后打开devtool
,接着在地址栏输入baidu.com
,可以看到网络面板的列表如下所示:
Connection ID
在列表中第一出现,按道理来说这个请求的时间线里面应该有initial connection
,但是有时候我们可能看不到initial connection
,原因有如下两个:
-
根据
http1.1
的那张图,我们知道http1.1
中采用的是长连接。可以在请求头中看到Connection: keep-alive
。但是如果长连接一直不关闭也非常占用服务器的资源。关闭长连接一般是两种方式:一是在请求头中加上Connection: close
。二是触发了服务器端的关闭长连接的策略。比如说nginx
中可以配置keepalive_timeout
来设置连接的超时时间,如果超过了keepalive_timeout
某个TCP
连接上还没有收到一个http
请求,那么服务器就主动断开连接。所以在network
中第一出现的TCP
没有看到连接的时间段,可能是因为这个TCP
还保持着。 -
TCP
连接是比较耗时的,为了优化网络性能,chrome
采用预连接来优化TCP
连接。具体细节可以查看chrome中的高性能网络
还需要注意的一点是:我们经常看到一句话:chrome
中一个域名下最多维持六个TCP
连接,很多时候在网络请求列表中我们可以看到一个域名下不止六个Connection ID
。并不是说这个说法是错的,而是因为有的TCP
的生命周期即将结束要被关闭了。可以通过netstat -ant -p TCP | grep "目标IP"
来查看处于ESTABLISHED
状态的TCP
。
Waterfall
waterfall
可以查看资源加载的时间线,如下图所示:
图中不同颜色的边框代表不同类型的资源,常见的边框颜色代表的资源类型如下所示:
将鼠标悬浮在waterfall
列,可以查看对应行所在请求的Timing
。
查看http
请求的详细信息
点开某一个http
请求,可以看到该请求的Headers
、Preview
、Response
、Initiator
和Timing
。
Headers
中展示的是http
请求头和响应头中的字段。Preview
和Response
的区别:Response
是浏览器的原始返回。而Preview
中是浏览器根据响应头中的Content-Type
处理过的Response
。比如当响应头中的Content-type
等于application/json
的时候Preview
会对返回的字符串进行了格式化,展示成json
格式方便查看;再比如当Content-type
等于text/html
的时候,Preview
会将Response
渲染成html
页面。Initiator
除了和列表中的Initiator
一样,可以查看这个请求的调用栈。还可以看到这个请求的启动链。调用栈指的是函数间的调用关系,而启动链是指文件之间的引用关系。Timing
可以查看该http
请求的时间线。
查看资源的依赖关系
按住shift
并将鼠标悬浮在其中某一个请求上,可以查看该资源的请求上下游。
如下图所示,表示请求app.6929d4b.css
是由juejin.cn
这个资源发起的。绿色的是上游启动器。
在列表中也可以看出app.6929d4b.css
的启动器:
如下图所示,标记为红色的资源都是jujin.cn
的下游的依赖资源。
复制请求
选中列表中的某一个请求,右键然后选中列表中的Copy
则可以复制该请求。如下图所示:
比如选中Copy as fetch
,则可以复制该请求然后粘贴在console
面板中重发该请求:
如果返回的是json
,可以通过await fetch("***").then(res => res.json()).then(json => console.log(json))
打印接口返回值。
重发请求
选中列表中的某一个请求,右键然后选中列表中的Replay XHR
则可以复制该请求。如下图所示:
预检请求
在请求列表中我们经常看到OPTIONS
和Prelight
等字段,也可以看到Method
为OPTIONS
的资源请求会在列表中出现两行。如下图所示:
这是因为CORS
且请求是复杂请求的时候,浏览器会自动先向服务器发送预检请求用于确认服务器是否支持该跨域请求。
符合以下条件之一的就是复杂请求:
- 请求的
Method
不是GET
、HEAD
和POST
- 请求的
Method
是POST
且Content-Type
不是text/plain
、application/x-www-form-urlencoded
或multipart/form-data
- 请求头中设置了自定义字段
详情可参考MDN CORS
资源请求信息概要
可以看到左下角有一组数据,来看看它们分别代表什么意思:
179 requests
: 打开devTools
后页面一共发送了179
个请求1.6MB transferred
: 网络传输的资源大小是75.8kb
4.2MB resources
: 网络传输的资源未压缩前的大小是4.2MB
Finish 3.81s
:所有http
请求从发送请求到响应完成的时间是3.81s
DOMContentLoaded 535ms
:HTML
文档解析完成和DOM
树构建完成的时间是535ms
Load 1.86s
:DOM
树构建完成后,继续加载html/css
中的img
、icon
等外部资源,加载完成后视为页面加载完毕。