之前简单的描述了Chrome Devtools的一些使用技巧,不过慢慢就会想想Chrome Devtools原理是什么呢 ?
一个简单的例子,我们用谷歌控制台去调试页面样式,页面可以根据调整的样式动态去变化,这是为啥?
这一切都可以 **[chrome devtools protocol](https://chromedevtools.github.io/devtools-protocol//)** 来解释。 Chrome DevTools Protocol 允许使用工具来检测、检查、调试和分析 Chromium、Chrome 和其他基于 Blink 的浏览器。 许多现有项目目前使用该协议。并且Chrome DevTools 使用此协议。因为功能比较多,所以分了多个域(一般复杂的东西都会分域),包括 DOM、Debugger、Network、Page 等等,分别放不同的调试协议。
新版 chrome可以打开设置中的实验特性的 Protocol Monitor 面板。
选择之后可以查看一下下,如果没有点击右侧三个点 然后里面有More tools进行添加。
一起⭕猜⭕一下上面css调试的整个过程。
- 修改了font-size的属性
- 3、4、5 等等发送了修改的请求
- 2是最后修改的300px,因为动态监听了这个所以发送了很多次 setStyleTexts 方法。
- 对照着 协议api可以了解到。
-
本质上就是在修改属性的时候 其实向 浏览器调试控制台发送request ,浏览器内部进行处理 并且给出状态。
这个仅仅是冰山一角的一角,可能会问了解这个有啥作用呢?
- 一方面 往高级点方向说就是 可以实现 CDP 服务端,来对接 chrome devtools 的调试功能,调试不同的目标,也可以通过 sdk 的 api 来和 CDP 服务端对接,拿到数据,实现调试的功能。比如单独实现 DOM 编辑器、Network 查看器、JS Debugger。
- 另一方面 还是返璞归真一些、能够了解一些浏览器工作原理、了解DOM树、了解CSS的一些知识、了解到请求是什么构成的?等等等很多
我们一起来来实验下:
1. 打开谷歌浏览器所在的文件位置 然后终端打开 输入 ./chrome --remote-debugging-port=9222 --headless
可以看到调试模式已经打开。可以将远程页面连入了。
2. 为了更好的看到一些效果,我用本地页面来进行, 这里需要注意的是 需要进行安装一下chrome-remote-interface 提供了一些简单的api。
下面代码意思很明显,先是navigate到给定URL的当前页面、通过页面上captureScreenshot 方法 获取当前页面的截图。这个方法可以传入很多参数。
打开谷歌浏览器 输入 ``chrome://inspect/#devices` 发现有一个远程页面了。
const CDP = require('chrome-remote-interface')
const fs = require('fs')
async function cdpTest() {
let client
try {
client = await CDP()
const {Page, DOM, Debugger, Network, CSS, Log, Browser} = client
await Page.enable()
await Page.navigate({url: 'http://localhost:63342/chrome-debugger-test/test.html?_ijt=j6tk8fq253465uofikto2bsqjb'})
const res = await Page.captureScreenshot()
fs.writeFileSync('./screenshot.jpg', res.data, {
encoding: 'base64'
})
} catch (err) {
console.error(err)
}
}
3. 通过这个协议继续查看一下页面中DOM元素 将这部分代码加入到上面代码的主体中。调试可以发现下面的整个文档的信息。等等,这是DOM树嘛?
然后找到其中一个DOM元素 通过getAttributes 获取属性查看一下。可以看到下面的信息。等等,怎么是数组的形式?
还有很多很多的api...
// 启用 DOM 代理
await DOM.enable()
// 获取整个树结构
const {root} = await DOM.getDocument({
depth: -1
});
console.log(root)
const result = await DOM.getAttributes({nodeId: 13});
console.log(result)
4. 继续往下去看看 CSS 部分在获取CSS信息之前需要等待DOM代理开启。通过getComputedStyleForNode方法获取元素的计算过后的样式。然后看到了写的color 变成了RGB形式存储了。元素面板右侧里面有个Computed。是不是正好对应?
// 页面中 class container 设置了颜色
.container{
color: #032dff;
}
await CSS.enable()
const nodeCssInfo = await CSS.getComputedStyleForNode({nodeId: 13})
5. 继续看看网络方面,我在页面中引入了JQ 然后发送了一个请求。然后可以看到一些信息。
await Network.enable();
//网络 requestWillBeSent->当页面即将发送HTTP请求时触发。
Network.requestWillBeSent((params) => {
console.log(params.request.url)
});