Chromium DevTools 架构
架构概览
宏观来看,DevTools 就是打开 Chrome 后 cmd+opt+i 开启的那个调试界面,但实际上远不止一个界面这么简单。DevTools 是一个典型的 CS 架构:
- target: 一个可调式目标,例如一个页面、Worker 都是可被调试的。而具体实现由 Blink Backend 完成
- client:任何想要连接到 target 的客户端,一般来说就是 DevTools
- session:client 与 target 的通信会话,使用 Chrome DevTools Protocol(CDP) 作为会话协议。
正因为这么一套架构,PC Chrome 可以调试 Mobile Chrome,VSCode 可以调试 PC Chrome。同样,任何浏览器只要能实现 Chrome DevTools Protocol,就可以使用 DevTools 进行调试。典型的就是多年前的 UC 浏览器。
CDP 使用 WebSocket 作为底层协议,所以 DevTools 本质上就是一套 WebSocket 通信系统,在 Devtools 进行的任何操作都会变成 CDP 命令发送给 Blink。同样,Blink 有任何反馈都会通过 CDP 同步给 DevTools。这与其他的 Debugger 是类似的,只是别的 Debugger 可能不使用网络协议作为通信手段,例如 LLDB。
在 DevTools 中可以方便的观察 CDP 发送和接受的内容,Experiments 中打开 Protocol monitor 即可。
DevTools UI
clone源代码
Chrome DevTools 与其他 Chromium 相关的基础设施类似,都通过 depot_tools 获取和同步上游仓库代码。
1fetch devtools-frontend // 拉取源代码
2cd devtools-frontend
3gn gen out/Default // 创建构建目录
4autoninja -C out/Default // 构建
使用本地构建的 DevTools
构建后的 DevTools 资源在 out/Default/gen/front_end,这是完全一个完全可用的 DevTools 版本,可以给 Chrome 添加 Cli 参数来让 Chrome 使用我们刚才构建好的本地 DevTools,以我本地路径为例:
1/Applications/Google\ Chrome\ Dev.app/Contents/MacOS/Google\ Chrome\ Dev --custom-devtools-frontend=file:///Users/z/Code/devtools-frontend/out/Default/gen/front_end
本地启动 Chrome Dev 版后,打开的 DevTools 就是我们的本地构建版本。
UI 工程架构
打开 devtools-frontend 的工程目录,可以看到它并不是我们常见的以视图框架为核心的前端工程结构,而是类似于 VSCode,以 Vanilla JS 方式对 DOM 进行编辑,以获取最小的性能开销和最高的性能。
整体架构如上图所示,devtools_app.ts 是 DevTools 的总入口,它 import 各个模块的入口,它们都以 *-meta.ts 命名,各个模块入口再向上层注册自己的 UI 内容。
Chrome Extension Debugger API
CDP 不仅为 DevTools 服务,Chromium Extension 也能通过Debugger API使用它,例如 React DevTools、Mobx DevTools 等都是使用 CDP 为其功能进行服务的。
Chromium 扩展的 Debugger API 支持 Chromium Extension attach 到一个调试目标,并且使用 CDP 进行调试。而 Chromium DevTools 本身也是通过 CDP 与 Blink 进行数据交互。通过 Protocol monitor 可以看到每一个在 DevTools 上的内部操作。