Web远程调试介绍

2024-02-19  本文已影响0人  cd2001cjm

引言:

在现代Web开发中,能够实时调试和监控应用程序已经成为了开发者日常工作的一部分。针对那些需求复杂、跨平台、并且必须随时保证高可用性的Web应用,一个高效、稳定的远程调试工具至关重要。在这篇文章里,我们将详细介绍CDP的概念以及其devtools的工作原理,同时介绍一个devtools的扩展chii并展示它是如何实现的。让我们从基本概念开始,逐步深入了解这一有用的工具。

一 、CDP介绍

Chrome DevTools Protocol(CDP)在调试网页和DevTools之间的交流过程中扮演了数据通信协议的角色。CDP定义了一套用于与Chrome的各种内部组件通信的底层命令和事件集合,这些组件包括但不限于:渲染、布局、JavaScript执行环境等。

具体到CDP的定位和作用:

  1. 定位:CDP位于DevTools前端与浏览器的后端(也就是渲染进程、网络栈等)之间,作为两者交互的桥梁。
  2. 作用

操作过程基本上是:当您进行某项操作时,比如点击DevTools中的“Elements”面板来检查页面元素,DevTools会通过CDP向浏览器发送一个命令,请求DOM树信息。浏览器接收到这个命令后,通过渲染进程查询具体的DOM信息,并将结果返回给DevTools,DevTools前端再将这些信息可视化呈现给开发者。

交换数据时的底层传输机制可能是IPC(适用于本地调试)或WebSocket(适用于远程调试),但无论具体使用哪种传输方式,CDP充当的角色和其功能不变。简言之,CDP提供了一种标准化的方式,让开发者能够以编程方式与Chrome浏览器互动,从而使自动化测试、远程调试等复杂的任务成为可能。

哪如果我们想实际给浏览器发送一个DCP命令该如何实现呢?

const WebSocket = require('ws'); // npm install ws

// 替换为实际的WebSocket调试URL,通常可以通过访问'http://localhost:9222/json'来获取
const wsUrl = 'ws://localhost:9222/devtools/browser/{sessionId}';

const ws = new WebSocket(wsUrl);

ws.on('open', function open() {
  // 发送一个CDP命令
  ws.send(JSON.stringify({
    id: 1, // 消息ID,用于匹配响应
    method: 'Runtime.evaluate', // 要执行的CDP方法
    params: {
      expression: 'console.log("Hello from CDP!");'
    }
  }));
});

ws.on('message', function incoming(message) {
  console.log('Received: %s', message);
});

注意,实际应用中您需要先启动Chrome以便开启远程调试功能,通常可以通过以下方式来启动(以命令行为例):

chrome --remote-debugging-port=9222

CDP的交互模式有两类:

那么在远程模式下,我们如何去打开展示一个devtools呢?

二、devtools-frontend

devtools-frontend 是 Chrome DevTools 的前端部分的源代码,它是用来与用户直接交互的图形界面,包括我们在使用 Chrome 浏览器开发者工具时看到的各种面板(如 Elements、Console、Network、Sources 等)。

如果你要参与 DevTools 前端的扩展开发或者了解其底层工作原理,你通常需要查看或者操作 devtools-frontend 代码库。这份代码库是开源的,可以在 Chromium 项目的代码库中找到。这样的开源性使得开发者可以深入学习 DevTools 的实现,甚至可以自定义 DevTools 的功能。

以下是与 devtools-frontend 相关的一些基本操作介绍:

  1. 查看源代码:你可以在 Chromium 的代码库中或者 Google 的 devtools-frontend 镜像库(如果有的话)中查看源代码。
  2. 运行 DevTools 前端:可以将 devtools-frontend 源代码下载到本地开发环境中,然后运行它。这通常需要配置一些环境变量,可能还需要安装一些依赖项。
  3. 修改和扩展:你可以在本地修改 devtools-frontend 的源代码,添加新的功能或者修改现有功能。这通常涉及到 JavaScript、HTML 和 CSS 的编写。
  4. 构建及部署:在完成代码修改后,你可以使用 Chromium 源代码中提供的构建系统来构建和测试你的更改。

devtools-frontend 是非常复杂的一套代码基础设施,它不仅包括用户界面,还有与后端(即浏览器引擎本身)的通讯逻辑。归功于 CDP,devtools-frontend 与浏览器的其他部分(例如渲染引擎、JavaScript V8 引擎等)保持不断的通信,这允许开发者实时监控和修改网页。

所以,我们可以自己部署一套devtools-frontend,我们先看本地模式的交互逻辑图:

image.png
本地模式

然后再看一下远程模式:

image.png
远程模式

对比我们可以看到:

在 Chrome DevTools 的体系中,后端充当了桥梁的角色,连接了正在调试的页面(也就是目标页面)和 DevTools 的客户端(用户界面)。

后端通常通过 WebSocket (ws) 协议与调试页面建立连接,使用 Chrome DevTools Protocol(CDP)来传送消息。而 DevTools 前端部分则通过一种叫做 IPC(Inter-Process Communication,即进程间通信)机制与后端(也就是浏览器的一部分)进行通信。

这里的过程可以大致描述如下:

目标页面与后端:

前端与后端:

用户交互流程:

这样的设计允许 DevTools 的前端和后端可以分离,甚至可以运行在不同的系统或者设备上,只要他们能够通过一些通讯协议(如 TCP/IP、WebSocket、IPC 等)交换 CDP 消息就可以了。

到这里为止我们发现远程调试的一个短板,就是需要chrome启动开debug端口,在这面向C端页面上是不可能的,你不能要求每个浏览器用户开启一个固定的端口。后来发现github有一个chii的项目,解决思路比较巧妙,下面我们一起来看一下。

三、Chii

Chii是一款web远程调试工具,其实现是对devtools-frontend的修改和扩展。它通过引入一层中介chobitsu,来解决我们上面所提到的需要浏览器开启debug端口的问题。chobitsu是CDP协议的JavaScript版本实现。其逻辑图如下:

image.png
chii逻辑架构图

它的使用非常的简单:

npm install chii -g
chii start -p 8080

在调试页面引入:

<script src="//host-machine-ip:8080/target.js" embedded="true"></script>

它本身分两种模式:

chobitsu也是chii团队提炼出的一个子功能。构思很是巧妙,目前基本能涵盖多数场景,比如Dom结构,Storage信息,CSS,Network,但仍然有关键的部位无法实现(js本身无法模拟)。

四、chobitsu的实现原理分析

首先,JavaScript是无法直接和CDP接口进行交互的。下面以它的一个DOM.ts

chobitsu源码

我们看到了什么?没错,是mutationObserver。到这里我们基本就对chobitsu实现理解有了了解。它并不是真正的去和浏览器的CDP接口进行交互,而是一种模拟实现。

再看一个Overlay.ts,鼠标在devtools的dom节点上滑动,调试页面会跟随高亮显示P:

overlay高亮显示

也是模拟,监听鼠标move事件,然后通过LunaDomHighlighter组件,对划过的元素进行高亮显示。

从这两个例子我们大概就能理解,chobitsu会接收真实的CDP指令,然后进行模拟实现。所以就有一个问题,

像断点调试这种需要真正调用CDP接口的,它依然无法实现。虽然没有做到完美,但其实已经解决了90%的问题了,后续我们可以一起想想,有什么解决思路。

结语:

在本文中,我们一起探索了网页远程调试的概念,面对的挑战,以及可能的解决方案。但关键还是要把这些知识用于实战,解决实际中的问题。例如,借鉴Chii这类工具,我们可以构建一个在线的远程调试页面,这对于移动设备尤其有效,它让我们可以清晰地掌握到真实设备的运行情况。

此外,这项技术在低代码环境下同样可以发挥作用,成为其中的一个便捷调试工具。不过,除了技术本身,更让人觉得有价值的是它背后的创新思维。别人如何将旧技术变新应用,勇于尝试的态度,这是我们应该学习和思考的。技术永远在变,学会借鉴别人的创意和

上一篇下一篇

猜你喜欢

热点阅读