实现DoKit Web端请求捕获工具(三)读Eruda源码下

·  阅读 518
实现DoKit Web端请求捕获工具(三)读Eruda源码下

一、前言

上一节的结论中,我们知道要请求捕获功能实现方案,我们需要关注package.json和src中源程序的内容。本节主要解析package.json和src目录下的文件,探讨ERuda Network模块的实现方案。

二、package.json解析

在Node.js中,模块可以是一个库或框架,也可以是一个Node.js项目本身。Eruda作为一个module,遵循Node.js项目模块化的架构,而模块的描述文件就是package.json。npm install执行时会将package.json中的依赖安装好;package.json的具体内容如下图:

参考Node.js项目的package.json详解,从Eruda的package.json中可以获得如下信息:

  • 应用入口文件为eruda.js
  • 项目应用开发环境依赖:ESLint、Webpack、Karma、Eustia、Jasmine等外部工具,项目可自动集成、代码检测、代码格式化、自动化测试等。
  • 使用了Express模版引擎hbs(handlebars)来渲染页面,用来书写模版的布局文件为.hbs文件,src/lib/handlebars.js中是hbs渲染事项的扩展信息;

三、src目录下源程序解析

src目录下文件结构如下:

  1. Eruda的各功能模块Console、Elements、Network、Resources、Sources、Info、Settings、Snippets分别对应一个文件夹;
  2. DevTools目录对应整个Eruda组件,包括上方的navbar和下方的tools(也就是上面的各功能模块);
  3. lib:lib中的util.js是使Eustia自动生成的JS函数库,abstract.scss、cssMap.js、evalCss.js、getAbstract.js等是为了加载字符串格式的css样式的文件。
  4. style:.scss样式文件;
  5. eruda.js:如二、所述,是项目的入口文件,加载Devtool模块,管理navbar间当前Tool的转换;
  6. index.js:module.exports = require('./eruda').default;为项目模块引eruda.js中export的eruda对象。

1.和2.中每个文件夹中都分别包含.scss、.js、.hbs三种文件,下面考虑这三种文件在功能实现中的作用。

.hbs是Express页面渲染引擎Handlebars.js的布局文件,Handlebars模板看起来和HTML一样,只是嵌入了handlebars表达式,handlebars表达式以{{开头,中间写一些内容,以}}结尾。

你可以使用"script"标签引入handlebars模板:

<script id="entry-template" type="text/x-handlebars-template">
  template content
</script>
复制代码

使用Handlebars.compile编译模板,然后传入上下文,handlebars就会执行并生成html。

四、src/network目录

  1. Network.scss Eruda Network部分的样式文件,在Network.js中由以下语句引入。

this._style = evalCss(require('./Network.scss'))

  1. Network.hbs、detail.hbs和request.hbs Eruda Network部分的布局文件,由Handlbars渲染成最终的html文件。我们可以查看最终Eruda Network的html文件及效果(它被加载到class为eerda-tools的div中,对应src/DevTools/Devtools.hbs中的内容):

由上可知Network.hbs是整体布局,其中引用了request.hbs和detail.hbs两个模块,可以看到Network板块包括title和request list上下两部分,request list中的ul列表加载每个request的基本信息:

点击request进入detail部分,展示reques的详细信息

  1. Network.js Network.js中包含请求捕获的实现代码,在下面重点研究。

五、Network.js

  1. 构造函数和重写的四个父类默认方法 Network类继承自Devtool/Tool类,父类中有init()/hide()/show()/destory()四个方法,包括构造方法,这些方法重写如下:
constructor() {
    super()

    this._style = evalCss(require('./Network.scss'))

    this.name = 'network'
    this._requests = {}
    this._tpl = require('./Network.hbs')
    this._detailTpl = require('./detail.hbs')
    this._requestsTpl = require('./requests.hbs')
    this._detailData = {}
  }
  init($el, container) {
    super.init($el)

    this._container = container
    this._bindEvent()
    this._appendTpl()
  }
  show() {
    super.show()

    this._render()    //渲染数据内容到$request、$detail这些DOM中
  }
  destroy() {
    super.destroy()

    evalCss.remove(this._style)

    const network = chobitsu.domain('Network')
    network.off('requestWillBeSent', this._reqWillBeSent)
    network.off('responseReceivedExtraInfo', this._resReceivedExtraInfo)
    network.off('responseReceived', this._resReceived)
    network.off('loadingFinished', this._loadingFinished)
  }
复制代码
  • 构造函数中传入了样式、布局文件和初始的request/detail数据;
  • init()初始化中传入容器对象、绑定页面元素的事件(如back、clear按钮的click事件和点击request显示其请求详情的事件)、打开chobitsu网络拦截、像页面元素内加载Network.hbs布局文件的内容;
  • show()显示Network面板时渲染数据内容到requestrequest、detail这些DOM中;
  • destory()销毁时移除该部分样式文件,关闭chobitsu网络拦截;
  • hide()未重写。
  1. 上方引用了Eruda自定义的chobitsu(是日文吗) 查看官方README.md看到,chobitsu是一个Chrome devtools协议的JS实现,它提供如下API:

要详细了解它的实现需要继续阅读它的源码,在Network.js中它在初始化(126行)、获得ResponsBody(110行)和销毁(173行)时被调用。

在使用chobitsu时传入了四个属性:requestWillBeSent、responseReceivedExtraInfo、responseReceived、loadingFinished,四个对象的数据信息如下所示:

1.requestWillBeSent

2.responseReceivedExtraInfo

3.responseReceived

4.loadingFinished

从四个对象的数据信息我们可以知道:

  • requestWillBeSent中在当前页面发送请求前,获取到了当前页面即将发送的请求的Request信息,如name、url、status、type和subtype、data、time等。(?但未找到是在哪里将即将发送的request list赋给_requests对象的,只有直接对它的使用,是chobitsu做的吗?)
  • responseReceivedExtraInfo中获取了request请求头中的其他信息。
  • responseReceived中是收到的response信息,包括响应头、状态码、请求是否出错、响应体等信息。(?得到相应信息是通过chobitsu.domain('Network').getResponseBody()获得的,所以是这条语句在浏览器发送请求前,预先发送了消息,从而提前拿到了响应信息的吗?)。
  • loadingFinished中计算好该请求的已展示时间,展示完成变标记为done,然后通过chobitsu.domain('Network').getResponseBody()获得响应信息,重新渲染页面。

六、本节总结

本节的主要结论是研究了Network.js源码后,发现了chobitsu这个chrome devtools协议工具,Eruda实现请求拦截是通过调用它实现的,本节研究了Eruda项目中是怎么调用它的,主要是传入了四个对象,获得了request的响应信息。

但要想具体了解请求捕获的实现方案,还需要带着以下问题继续阅读chobitsu的源码:

  • 怎么获得request list的,是在真正发送请求之前吗?
  • 何时发送的请求,在请求发送前都做了什么?
  • 获得response信息是chobitsu自行发送了请求后记录了response信息,还是直接记录了浏览器发送请求所获得的response?
  • chobitsu是怎么拦截请求的,是它重写了浏览器发送请求的send方法,在原有的send前做了些其他事吗?

七、文章索引

实现DoKit Web端请求捕获工具(一)产品调研

实现DoKit Web端请求捕获工具(二)读Eruda源码上

实现DoKit Web端请求捕获工具(三)读Eruda源码下

分类:
开发工具
标签:
分类:
开发工具
标签:
收藏成功!
已添加到「」, 点击更改