最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【技术攻略】抖音小程序 / 小游戏调试原理

    正文概述 掘金(抖音小程序团队)   2021-04-07   1427

    作者:黄俊铭,抖音小程序前端开发工程师

    基础概念

    首先需要提到的是,chrome 与 V8 本身实现了一套调试协议:chromedevtools.github.io/devtools-pr…

    比如我们在 chrome devtool 打了一个断点,devtool 会自动产生协议消息,V8 获得协议消息之后也能对该协议消息进行解析产生相应的反馈,产生协议消息再给 chrome devtool, chrome devtool 再展示相应的变量信息等。

    如下图,拦截了 ws 消息,可以看到协议中产生的消息自动产生了 id 序列号码以及方法(绿色的是 chrome devtool 发出的消息,红色是从 V8 发来,chrome devtool 接收到的消息)。 【技术攻略】抖音小程序 / 小游戏调试原理

    本地调试

    【技术攻略】抖音小程序 / 小游戏调试原理 小程序/小游戏在内部包支持本地直接连接 USB 进行本地调试,在没有配置远程调试链接模式下,默认在初始化V8引擎后,内部会在本地开启一个websocket server,端口为9229。

    同时这个websocket server需要支持/json(更多可以参考:chromedevtools.github.io/devtools-pr… ),这样chrome就能在 chrome://inspect 界面找到该调试。

    具体操作就是,手机设备先连接USB线,然后执行 adb forward tcp:9229 tcp:9229 转发端口到电脑设备,这时我们可以访问 localhost:9229,可以看到如下数据,描述了调试调试链接等信息。

    [
      {
        "description": "helium v8 inspect",
        "devtoolsFrontendUrl": "chrome-devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/helium",
        "title": "helium",
        "id": "helium",
        "type": "node",
        "url": "file://",
        "webSocketDebuggerUrl": "ws://127.0.0.1:9229/helium"
      }
    ]
    

    打开 chrome://inspect,可以配置寻找的相应端口号 【技术攻略】抖音小程序 / 小游戏调试原理

    最后从 chrome://inspect 可以看到 【技术攻略】抖音小程序 / 小游戏调试原理

    点击 inspect 则打开 json 结构中的 devtoolsFrontendUrl

    chrome-devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/helium
    

    可以观察发现ws=127.0.0.1:9229/helium 其实就是告诉chrome devtool去连接该链接的websocket server,这样的话就 websocket server 就能收到 devtool 传来的调试协议消息,然后传给 v8,v8 产生协议消息后再给websocket server向devtool发送消息,这样就产生了整个调试通路。

    远程调试

    【技术攻略】抖音小程序 / 小游戏调试原理 本地调试是我们的内部调试方式,并且使用 USB 调试比较麻烦,为了解决开发者的调试,我们加了一个远程调试逻辑,其实原理也很简单,我们通过一个远程的中转 websocket 服务器,客户端不再作为 server,而是作为 client,然后 client 连接远程服务端,devtool 也连接远程服务端,devtool 发送断点调试信息给远程服务端,远程服务端将该信息透传给手机中的 v8,这样就形成了通路。

    其实对于抖音小程序小游戏场景,其中还有一个角色是开发者工具IDE(electron),IDE包含了chrome devtool,整体的运行流程如下:

    • 开发者开发完成,点击开发者工具的真机调试
    • 开发者工具连接远程服务端,获取调试房间id,将房间id带入了二维码信息中,产生了二维码
    • 带有小程序的手机扫码,获取调试房间id后连接到远程服务器的同一个房间中
    • 这时候设备中的V8就可以与chrome devtool通过远程服务器的房间进行转发通信消息,也就形成了整个调试通路

    小程序 webview 调试

    【技术攻略】抖音小程序 / 小游戏调试原理

    对于小程序场景还有一个 webview 的调试,那我们也要一起支持远程调试,怎么做呢? 其实从 chrome://inspect 本身我们可以看到开了debug设置的webview本身就是可以调试的,其实我们就可以猜想到 webview 本身在手机就起了服务,因此我们只要同样连上这个服务,就可以往里面收发消息完成远程调试了。 【技术攻略】抖音小程序 / 小游戏调试原理

    如下,chrome for android其实开启了unix domain socket。 【技术攻略】抖音小程序 / 小游戏调试原理

    所以只要连接上它们就行了,然后再新增一个websocket client,将我们从原本的远程Websocket client收到的 DOM 调试信息转发给该unix domain socket,client从该unix domain socket 收到消息转发给远程服务器,最后devtool就可以收到 webview DOM的调试信息。

    可以看到上面的示意图,相比前一节新增了一个 WebSocket client(webview)以及 Webview Unix Socket 的模块,通过它们的转发通信,我们就实现了远程调试小程序的页面元素。

    V8 调试模块

    下述讲解 V8 调试模块接入的一些核心类,包含 v8_inspector::V8InspectorClient、v8_inspector::V8Inspector、v8_inspector::V8InspectorSession、v8_inspector::V8Inspector::Channel等,有兴趣接入 V8 调试模块业务可以作为参考,整体工作流程如下所示: 【技术攻略】抖音小程序 / 小游戏调试原理 代码示例:

    // 创建 Channel
    // 需要自己实现 Channel
    // class ChannelImpl final: public v8_inspector::V8Inspector::Channel
    v8_inspector::V8Inspector::Channel channel_ = new ChannelImpl();
    v8_inspector::StringView view( ... )
    
    // 创建 session
    // 连接 inspector 和 channel
    v8_inspector::V8InspectorSession session_ = 
        inspector_.connect( 
            1, 
            channel, 
            view);
    
    // 需要调用 contextCreated 
    // 将上下文信息传入 inspector
    // ctx_name 为上下文名字
    v8_inspector::StringView ctx_name( /*ctx_name*/ )
    inspector_->contextCreated(、
        v8_inspector::V8ContextInfo(
            context, 
            1, 
            ctx_name);
    

    v8_inspector::V8InspectorClient

    class V8_EXPORT V8InspectorClient {
     public:
      virtual ~V8InspectorClient() = default;
    
      virtual void runMessageLoopOnPause(int contextGroupId) {}
      virtual void quitMessageLoopOnPause() {}
    };
    

    这个类我们主要需要实现两个函数,一个是runMessageLoopOnPause,一个是quitMessageLoopOnPause

    • runMessageLoopOnPause

    在断点的时候,v8 会触发 runMessageLoopOnPause,这时候需要接入方同步的消费所有来源于 devtool 消息(消费即传入 v8 驱动运行),我们需要开启自己的messageLoop去消费消息,否则会导致丢失所有 devtool 发来的消息的作用,现象就是拿不到上下文信息,console 控制台将无效没有反应

    • quitMessageLoopOnPause

    将结束断点的时候,就会自动触发 quitMessageLoopOnPause,这时候我们可以停止 MessageLoop,不需要再继续进行同步地消费消息了

    v8_inspector::V8Inspector

    这个类构造时需要传入两个参数,一个是isolate,一个是上述我们所讲的V8InspectorClient实例,首先需要说的是,一个v8Inspector对应一个isolate,一个isolate下有多个context,因此其实一个inspector可以调试多个context。

    v8_inspector::V8Inspector::Channel
    // Connection.
      class V8_EXPORT Channel {
       public:
        virtual ~Channel() = default;
        virtual void sendResponse(int callId,
                                  std::unique_ptr<StringBuffer> message) = 0;
        virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0;
        virtual void flushProtocolNotifications() = 0;
     };
    

    channel是跟v8inspector的通道,可以获取到v8内部产生的协议消息,需要做的事情就将它转发给 devtool,主要需要实现sendResponse和sendNotification,其实很简单直接将消息转发给devtool就行了

    void sendResponse(int callId, std::unique_ptr<v8_inspector::StringBuffer> message) override {
        sendToDevtool(message->string());
    }
    void sendNotification(std::unique_ptr<v8_inspector::StringBuffer> message) override {
        sendToDevtool(message->string());
    }
    

    v8_inspector::V8InspectorSession

    通过连接channel和inspect产生调试session,这个session主要用来接收devtool传来的消息,然后将消息通过方法dispatchProtocolMessage 可以将协议消息传给v8,从而驱动v8断点等行为,然后v8会调用channel方法再将内部协议消息传达出来,整个链路就走通了。

    std::unique_ptr<StringBuffer> &str = messages.front();
    session->dispatchProtocolMessage(str->string());
    

    参考资料

    • v8.dev/docs/inspec…
    • chromedevtools.github.io/devtools-pr…
    • medium.com/@hyperandro…

    起源地下载网 » 【技术攻略】抖音小程序 / 小游戏调试原理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元