|
前两期讨论了 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?以两种方式存在:通过 Chrome 插件商店?获取插件版本,具体参考使用文档;通过?Npm?安装独立的 Standalone 版本,增强远程调试功能, 集成 Chrome Devtools 的远程调试功能,方便的调试移动端页面,一般推荐使用;Standalone 版本支持两种调试模式,如下视频演示:针对 San 应用的远程调试模式;适用任何环境的 Chrome 远程调试模式,支持移动端 H5、IE、Safari 等环境;核心概念San DevTools?是支持?San?应用开发的调试工具。为了方便大家理解其中的概念,我们先思考如下的问题:如何从零设计 & 实现一款远程调试工具?实现查看组件树功能。首先,我们应该能想到需要有两个模块,一个是调试的工具,一个是被调试的目标页面。按照远程调试工具的传统,站在开发工具的角度,把工具页面叫做?Frontend,被调试的目标页面叫做?Backend,和传统前后端开发概念有点类似。其次,前后端的通信问题要先考虑,如何设计方便前后端模块发送事件呢?参考前端与 NA 端桥接?Bridge?的概念,设计了 Bridge 实例,各模块内部通过实例方便地发送事件。// Serverimport 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 Bridgeconst wss = new WebSocket('wss://localhost:8080');const bridge = new Bridge({ listen(fn) { wss.onmessage = fn; }, send(data: any) { wss.send(data); }});再次我们思考几个问题:前后端可不可以直接通信?收集、计算 Backend 页面数据的模块如何设计?格式要不要规范(类似 RESTFul 格式)?对这几个问题分别进行分析:通信协议大家直观能想到要用 WebSocket 技术,前后端其实都是跑在浏览器里的页面,显然不能直接通信,需要服务端做中间联接;收集数据的模块需要监听、操作页面的 JS/Dom 等,这里用了非常形象的?Hook?概念与模块;计算处理数据的工作会比较多,比如组件树数据的计算生成,组件路径数据等等,这部分主要工作是代理?Frontend?与?Backend?之间数据的交互处理,所以有了?Agent?模块;传统前后端开发会有 RestFul 风格接口、接口规范文档等,我们的?Backend?与?Frontend?同样需要一定的规范,这就是?Remote Debugging Protocol?协议规范,为了实现交互的标准规范;在服务端需要建立对应的前后端消息联接,叫做?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:类似于前端与 NA 端建立的桥接,方便前后端发送消息通信;Hook:目标页面勾子,与调试的页面深入结合,可操作目标页面的 JS/DOM,并监听发出来的事件比如组件生命周期事件,主要功能是收集页面数据;Agent:目标页面的数据处理模块,数据来源为 HOOK 收集的数据或者通过 Bridge 接收到的数据,处理之后的数据会通过 Bridge 发送出去抑或存储在目标页面。架构 & 流程下面是 San DevTools 的整体架构图整体流程如下图所示Frontend & BackendFrontend?与?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?日
|
|