使用ZanProxy远程调试页面(插件增强)

2018-08-10 admin

目的

远程调试页面的工具有很多,像Charles、spy-debugger等等,但是上次介绍ZanProxy的文章中已经把这些工具都扔掉了……所以要想一个办法能实现远程调试,但是又不打脸,于是就有了使用ZanProxy插件的方案,本文将细细道来。

插件

根据官方文档编写插件 · ZanProxy一节,可以得知:

ZanProxy插件是是一个npm包,这个npm包需要导出一个类,这个类要实现两个方法:proxy和manage,除此之外没有任何特殊要求。 proxy方法用于请求的处理,manage方法用于插件的配置。

// 最简单的结构框架
module.exports = class RemoteDebugPlugin {
  proxy() {}
  manage() {}
}

需求

前端的远程调试,无非就是希望能将远端的资源切换成本地的,以及能够看到开发者工具中的一系列信息(如控制台输出、网络请求等)。那么资源的切换可以通过代理去实现(之前的文章中已经讲过,通过ZanProxy的Hosts管理和Http转发),而查看控制台输出的需求,只有当页面的载体是PC端的浏览器才可以(任何端的Webview以及移动端的任何都不行)。 不使用第三方工具,我们能做的就只有在页面上模拟一个开发者工具,通过大量的search和compare,最终有两家入选——vConsole & eruda

vConsole vs eruda

vConsole

腾讯开发的一个轻量、可拓展、针对手机网页的前端开发者调试面板官方文档

注入后页面右下角将会多出一个绿色的vConsole悬浮按钮:

vConsole

eruda

Eruda 是一个专为手机网页前端设计的调试面板,类似 DevTools 的迷你版,其主要功能包括:捕获 console 日志、检查元素状态、捕获XHR请求、显示本地存储和 Cookie 信息等等。官方文档

注入后页面右下角将会多出一个图标为齿轮浮层:

eruda

各取所需吧,感觉这两个都很不错。但由于vConsole的文档更像详细,所以我在这里选择了vConsole。下文均基于vConsole进行介绍,如需使用eruda,改动是非常小的,将vConsole的配置部分按照文档修改成eruda的即可,对于ZanProxy是无感的。

实现proxy方法

不论是使用vConsole还是eruda,其本质都是在页面内添加一段script脚本,所以我们需要拦截html文件,在header部分 插入对应的script脚本后返回给客户端使用。

const { byteLength } = require('byte-length')
const zlib = require('zlib')

proxy() {
  return async (ctx, next) => {
    const contentType = ctx.res.getHeader('content-type')
    const contentEncoding = ctx.res.getHeader('content-encoding')
    if(contentType === 'text/html') {
      // 只拦截html文件
      ctx.res.body.on('end', () => {
        let contentString = ctx.res.body
        // 如果是gzip的话,需要解压
        if(contentEncoding === 'gzip') {
          contentString = zlib.gunzipSync(contentString)
          ctx.res.removeHeader('content-encoding')
        }
        contentString = contentString.toString()
        // 找到插入点(head闭合标签前、第一个script标签前,取最靠前的一个)
        const headEndIndex = contentString.indexOf('</head>')
        const firstScriptIndex = contentString.indexOf('<script>')
        const injectIndex = Math.max(...[headEndIndex, firstScriptIndex].filter(i => i > -1))
        if(injectIndex > -1) {
          // 插入所需要的脚本代码
          const vconsoleScript = '<script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script><script>new VConsole();</script>';
          const result = contentString.slice(0, injectIndex) + vconsoleScript + contentString.slice(injectIndex, contentString.length)
          ctx.res.setHeader('content-length', byteLength(result))
          ctx.res.body = result
        }
      })
    }

    await next()
  }
}

实现manage方法

manage方法是为了提供页面来对当前插件进行管理。按照上面方式实现的zan-proxy-remote-debug-plugin插件,vConsole会永久在所有的html页面中展示,所以我们需要通过manage方法在页面中对vConsole的展示与否进行控制。

const Koa = require('koa')
const Static = require('koa-static')
const Router = require('koa-router')
const BodyParser = require('koa-bodyparser')
const path = require('path')
const jsonfile = require('jsonfile')
const os = require('os')

// 配置文件存放路径
const configFilePath = `${os.homedir()}/.front-end-proxy/plugins/zan-proxy-remote-debug-plugin.config.js`
class RemoteDebugPlugin {
  constructor() {
    this.vconsole = true
    // 读取配置文件覆盖默认配置
    const config = jsonfile.readFileSync(configFilePath)
    config && (this.vconsole = config.vconsole)
  }

  proxy() { /* 此处忽略proxy的实现 */}

  manage() {}
}
manage() {
  // manage方法需要返回一个Koa实例
  const app = new Koa()
  // 我们将静态资源放置在static目录下
  app.use(Static(path.resolve(__dirname, './static')))
  app.use(BodyParser())
  // 通过router接收请求,修改配置
  const router = new Router()
  // 列出配置详情
  router.get('/config', async (ctx) => {
    ctx.body = { vconsole: this.vconsole}
  })
  // 修改vConsole启用状态
  router.post('/vconsole', async (ctx) => {
    this.vconsole = ctx.request.body.enable
    jsonfile.writeFileSync(configFilePath, { vconsole: this.vconsole })
    ctx.body = { vconsole: this.vconsole }
  })
  app.use(router.routes())
  app.use(router.allowedMethods())
  return app
}

既然已经有了配置文件,那么我们需要改造一下proxy方法,通过配置来确定是否需要执行页面请求的拦截。

if(contentType === 'text/html') {}

↓↓↓修改为↓↓↓

if(this.vconsole && contentType === 'text/html') {}

实现manage页面

manage页面其实是上面Koa引用的一个静态资源./static/index.html,我们需要实现这个页面。

<input type="checkbox" id="vconsole">启用vConsole
<script>
const configUrl = '/plugins/zan-proxy-remote-debug-plugin/config'
fetch(configUrl).then(res => res.json()).then(config => {
  // 获取配置文件中的配置并设定
  const vConsoleSwitcher = $('#vconsole')
  vConsoleSwitcher.prop('checked', config.vconsole)
  // 用户修改配置时进行同步
  vConsoleSwitcher.change(function (e) {
    fetch('/plugins/zan-proxy-remote-debug-plugin/vconsole', {
      method: 'post',
      body: JSON.stringify({ enable: e.target.checked }),
      headers: { 'Content-Type': 'application/json' }
    })
  })
})
</script>

完成后的manage页面大概长这样: manage页面

收尾

上面的步骤都完成以后,将代码以npm包的形式发布到任意一个registry就可以了,在ZanProxy的插件管理页面添加一个插件,填写好包名和registry,尽情享受你的调试插件吧!~ 当然也可以直接用我写好且已经发布了的插件,包名:zan-proxy-remote-debug-plugin,registry空着不填就可以(默认是registry.npmjs.org/)。

原文链接:https://coderge.com/articles/201808/zan-proxy-remote-debug-plugin.html

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-37657.html

文章标题:使用ZanProxy远程调试页面(插件增强)

相关文章
Bootstrap 下拉多选框插件Bootstrap Multiselect
引入文件: &lt;link rel=&quot;stylesheet&quot; href=&quot;css&#x2F;bootstrap.min.css&quot; type=&quot;text&#x2F;css&quot;&#x2...
2017-02-22
AngularJS:何时应该使用Directive、Controller、Servic
AngularJS是一款非常强大的前端MVC框架。同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉。(译者注:老外真谦虚,我大天朝的码农对这些概念那是相当熟悉啊!)这些概念有: Directive(指令) Controller(控制...
2015-11-11
vue使用watch 观察路由变化,重新获取内容
问题背景: 点击用户头像 =&gt; 进入用户个人中心,在用户个人中心里点击其他用户的头像,我希望显示被点击用户的个人中心,但只看到了路由参数在发生变化,页面内容并没有更新。如图: 页面代码如下: &lt;script&gt; exp...
2017-03-13
使用 Protocol Buffers 代替 JSON 的五个原因
在 Ruby 和 Rails 开发者中,面向服务 (Service-Oriented) 架构有一个当之无愧的名声,它是一个缓解程序规模恶性增长的一个强有力的途径,可在大量应用程序中提取关注点。这些新生小巧的服务通常继续使用 Rails 或 ...
2016-01-13
Bootstrap table简单使用总结
最近接触一个很棒的插件,Bootstrap table没做过前端的表示对table的印象还只停留在html的table标签那一套,用过bootstrap table之后不得不说真的很实用。 构造方式 1 、HTML &lt;div clas...
2017-03-17
如何使用JavaScript
一、应用&lt;script&gt;标签加入JavaScript 任何脚本语言均可以通过&lt;script&gt;…&lt;/script&gt;标记对加入到HTML代码中(即是加入到网页文档&lt;html&gt;…&lt;/html&...
2015-11-12
ajax教程之ajax使用Http请求
ajax中是如何让使用http请求的呢? 在传统的JS编程中,如果您希望从服务器上的文件或数据库中得到任何的信息,或者向服务器发送信息的话,就必须利用一个 HTML 表单向服务器 GET 或 POST 数据。而用户则需要单击“提交”按钮来发...
2015-11-12
bootstrapValidator.min.js表单验证插件
本文实例为大家分享了bootstrapValidator.min.js表单验证的具体代码,供大家参考,具体内容如下 注意:下载后全选复制并粘贴到新建js文件名为bootstrapValidator.min.js下即可。 测试代码: &lt;...
2017-03-17
JS实现的通用表单验证插件完整实例
本文实例讲述了JS实现的通用表单验证插件。分享给大家供大家参考。具体如下: 这里演示一个通用的JS表单验证插件代码。使用方法:第一步:需设定表单项数据类型,第二步:实例表单验证,验证错误提示说明(程序有自带相关错误提示,可自定义每项验证错误...
2017-03-29
vue-awesome-swiper的使用以及API整理
一、先说一个看关于vue-awesome-swiper的一个坑 vue项目的package.json中显示的&lt;span style=“color: orange;”&gt;“vue-awesome-swiper”: “^2.5.4”&...
2018-04-26
回到顶部