San DevTools 技术解析(上)

前两期讨论了 San CLI 的使用和实现原理,从这篇文章开始我们会通过上中下三篇文章来介绍 San DevTools 技术实现,满满干货,不容错过!

前言

今天我们带来《San DevTools 技术解析》上、中、下三篇系列话题,带大家深入理解 DevTools 底层原理,通过关键技术的讲解,理解 DevTools 底层设计原理,理解 San 与 DevTools 如何通信?Standalone 版本如何调试多种场景?WebSocket 通信如何实现?Chrome 插件应用到哪些技术?远程调试如何实现?调试协议有哪些有意思的应用场景等等。

San DevTools
整体涉及的技术点较多,希望通过本文大家能够理解掌握关键技术与设计。

这是《San DevTools 技术解析》第一篇文章,重点介绍下 San DevTools 的主要功能、整体架构和重要的模块概念。

PS:在 San DevTools 中我们集成了 Chrome DevTools,可以实现远程调试 Webview 页面,即使不是 San 用户,也可以使用该工具 远程调试
手机 / 模拟器中的页面,并且不需要安装 inspect 内核。是时候替换 vconsole 之类的调试工具了,来试试我们的 Chrome DevTools 远程调试吧!

整体介绍

功能简介

San DevTools
以两种方式存在:

  1. 通过 Chrome 插件商店 获取插件版本,具体参考使用文档;

  2. 通过 Npm 安装独立的 Standalone 版本,增强远程调试功能, 集成 Chrome Devtools 的远程调试功能,方便的调试移动端页面,一般 推荐使用

Standalone 版本支持两种调试模式,如下视频演示:

  1. 针对 San 应用的远程调试模式;

  2. 适用任何环境的 Chrome 远程调试模式,支持移动端 H5、IE、Safari 等环境;

核心概念

San DevTools
是支持  San
应用开发的调试工具。

为了方便大家理解其中的概念,我们先思考如下的问题:

如何从零设计 & 实现一款 远程调试工具
?实现查看组件树功能。

首先,我们应该能想到需要有两个模块,一个是调试的工具,一个是被调试的目标页面。按照远程调试工具的传统,站在开发工具的角度,把工具页面叫做 Frontend
,被调试的目标页面叫做  Backend
,和传统前后端开发概念有点类似。

其次,前后端的通信问题要先考虑,如何设计方便前后端模块发送事件呢?参考前端与 NA 端桥接 Bridge
的概念,设计了 Bridge 实例,各模块内部通过实例方便地发送事件。

// Server
import WebSocket from 'ws';


const wss = new WebSocket.Server({port: 8080});


wss.on('connection', ws => {
const bridge = new Bridge({
listen(fn) {
ws.on('message', fn);
},
send(data: any) {
ws.send(data);
}
});
});


io.listen(8080);
// Backend/Frontend Bridge
const wss = new WebSocket('wss://localhost:8080');


const bridge = new Bridge({
listen(fn) {
wss.onmessage = fn;
},
send(data: any) {
wss.send(data);
}
});

再次我们思考几个问题:

  1. 前后端可不可以直接通信?

  2. 收集、计算 Backend 页面数据的模块如何设计?

  3. 格式要不要规范(类似 RESTFul 格式)?

对这几个问题分别进行分析:

  1. 通信协议大家直观能想到要用 WebSocket 技术,前后端其实都是跑在浏览器里的页面,显然不能直接通信,需要服务端做中间联接;

  2. 收集
    数据的模块需要监听、操作页面的 JS/Dom 等,这里用了非常形象的  Hook
    概念与模块; 计算处理
    数据的工作会比较多,比如组件树数据的计算生成,组件路径数据等等,这部分主要工作是代理  Frontend
    与  Backend
    之间数据的交互处理,所以有了  Agent
    模块;

  3. 传统前后端开发会有 RestFul 风格接口、接口规范文档等,我们的 Backend
    与  Frontend
    同样需要一定的规范,这就是  Remote Debugging Protocol
    协议规范,为了实现交互的标准规范;

  4. 在服务端需要建立对应的前后端消息联接,叫做 Message Channle
    消息通道,或更形象点叫  房间
    ,消息不可以在不同房间内『串门』,保证消息的准确性;

总结
:通过本节的介绍我们明白了远程开发调试必备的 四大核心模块

  • Frontend:
    调试工具前端,在  Chrome DevTools
    里包括我们经常看到的 Elements、Console、Network、Source 等面板;在  San DevTools
    我们实现了 Component、History、Store、Event、Message 等面板;

  • Backend:
    调试器后端,注入到运行中的页面,从调试工具的角度看属于  Backend
    (稍注意下概念,和传统前端理解不太一致);

  • Protocol:
    调试协议,连接 Frontend 与 Backend 的交互协议,通过定义方法和事件提供双方的交互,包括相应的 JSON 数据格式;

  • Message Channel:
    消息通道,为实现 Frontend 与 Backend 的通信设计,包括 WebSocket Channel,Chrome Embedder Channel,Chrome Extensions Channel;

除四大核心概念外,为实现相应的功能引入三个概念与模块:

Bridge
Hook
Agent

架构 & 流程

下面是 San DevTools 的整体架构图

整体流程如下图所示

Frontend & Backend

Frontend
与  Backend
有较多的交互流程,我们把这两个模块放在一起来说。

在不同的流程阶段,有不同的关键技术实现,我们分两个阶段进行说明。

初使化阶段

初使化阶段关键技术点:

  • Chrome 插件与 Standalone 版本,入口方面不同,Chrome 插件通过配置 manifest.json
    实现入口,技术详情请参考本文的后续章节;

  • Standalone 版本会启动一个 Node 服务,提供 JS 文件,需要注入 JS 到调试的页面,实现页面数据的收集计算;

  • Hook
    注入并劫持全局变量  __san_devtool__
    ,所有和 San 框架相关的交互都是通过这个变量,比如 San 版本号等;具体可以直接通过控制台打印变量;

联接的建立:

  • 两次握手协议事件的发送,最终确认联接建立成功;

  • 核心是建立两个 Bridge 桥接实例;

  • 前后端的联接建立使用的是 WebSocket 或 Chrome Runtime 的长联接;

Standalone 功能更强大,支持任意页面的远程调试能力,与业界同类工具相比更优,比如 VConsole、Weinre 等:

  • 基于 Chrome DevTools Frontend 作为前端的调试面板,更符合前端同学的调试习惯,功能也更强大;

  • 适用于各种浏览器环境,比如移动端 H5 页面、IE、Safari、Native 等等;

其他节点阶段

这里我们以组件信息同步与组件树渲染两个阶段为例,这两阶段技术具有代表性:

  • DevTools 需要加载开发版 San (san.dev.js),才能支持调试工具;

  • San 通过 DevTools 注入的全局变量发送生命周期数据(其他数据也一样);

  • 组件树数据的生成是通过组件 attach 事件,在 Backend 页面记录并生成;同理大部分的数据收集与计算是在 Backend 实现的;

最后

感谢你阅读到了这里,以上便是《San DevTools 技术解析 (上)》的全部内容。

今天带着大家设计一款远程调试工具的思考,并形成四大核心概念与模块,并且介绍了其中的两部分: Frontend
与  Backend
,它们在不同阶段的关键技术。

下期介绍 Message Channel
和  Debugging Protocol
,是整个工具核心的两部分内容,并且还是很有意思的技术,比如通信协议如何实现的;我们能干点啥;自动化测试脚本;无头浏览器;Chrome 的 Fronend 复用等等都将在下节揭晓。

期待下期《San DevTools 技术解析 (中)》再见!

EOF

作者:廖焕宇 刘斌

2020 年 12 月 23 日

百度App技术
我还没有学会写个人说明!
上一篇

【Python 1-14】Python手把手教程之——详解函数的高级用法

下一篇

辛选回应“燕窝事件”处罚:接受并积极整改

你也可能喜欢

评论已经被关闭。

插入图片