深入了解-微信开发者工具

Posted 骑摩托的蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解-微信开发者工具相关的知识,希望对你有一定的参考价值。

主要介绍微信开发者工具如何编译小程序代码,如何实现小程序模拟器以及如何调试小程序。

1 简介

虽然在开发语言层面小程序与传统的网页差别不大:是使用javascript 脚本语言编写逻辑代码、使用类似于html的WXML来描述页面的结构、使用类似于CSS的WXSS来描述节点的样式,但是由于小程序渲染和逻辑分离的运行机制与传统的网页存在差异,所以无法使用传统的网页的开发调试工具,因此我们使用小程序开发生态一站式IDE——微信开发者工具。开发者可以借助微信开发者工具完成小程序的代码开发、编译运行、界面和逻辑调试、真机预览和提交发布版本等功能。

图1 微信开发者工具

微信开发者工具是一个基于nw.js ,使用node.js、chromium以及系统API来实现底层模块,使用React、Redux等前端技术框架来搭建用户交互层,实现同一套代码跨Mac和Windows 平台使用。

图2 微信开发者工具底层框架


2 代码编译

微信开发者工具和微信客户端都无法直接运行小程序的源码,因此我们需要对小程序的源码进行编译。代码编译过程包括本地预处理本地编译和服务器编译。为了快速预览,微信开发者工具模拟器运行的代码只经过本地预处理、本地编译,没有服务器编译过程,而微信客户端运行的代码是额外经过服务器编译的。

 

1 编译WXML 

WXML(WeiXin Markup Language)是小程序框架设计的一套标签语言,用于构建出页面的结构。小程序的渲染层的运行环境是一个WebView,而WebView无法直接理解WXML标签,所以需要经过编译。
微信开发者工具内置了一个二进制的WXML编译器,这个编译器接受WXML代码文件列表,处理完成之后输出JavaScript代码,这段代码是各个页面的结构生成函数

图3 WXML的编译过程

编译过程将所有的WXML代码最终变成一个JavaScript 函数,预先注入在WebView中。在运行时确定了页面路径之后,将路径作为参数传递给这个函数得到该页面的结构生成函数,页面结构生成函数接受页面数据,输出一段描述页面结构的JSON,最终通过小程序组件系统生成对应的HTML

代码清单1 如何使用页面结构生成函数

//$gwx 是WXML编译后得到的函数
//根据页面路径获取页面结构生成函数
var generateFun = $gwx('name.wxml')
//页面结构生成函数接受页面数据,得到描述页面结构的JSON
var virtualTree = generateFun(
   name:  'miniprogram'
)
/** virtualTree == 
   tag: 'view',
   children: [
       tag: 'view',
       children: ['miniprogram']
     ]
 **/
 //小程序组件系统在虚拟树对比后将结果渲染到页面上
 virtualDom.render(virtualTree)

上传代码时,微信开发者工具直接将本地的WXML代码文件提交到后台,由后台进行WXML编译,后台的WXML编译器和开发者工具本地内置的WXML编译器是同一套代码生成的。

2 编译WXSS

WXSS (WeiXin Style Sheets) 是一套样式语言,用来决定 WXML 的组件应该怎么显示。为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。与 CSS 相比,WXSS 扩展的一些特性,包括rpx尺寸单位和样式导入语法,这些特性都是WebView无法直接理解的。
微信开发者工具内置了一个二进制的WXSS编译器,这个编译器接受WXSS文件列表,分析文件之间的引用关系,同时预处理rpx,输出一个样式信息数组,如图4,每个WXSS文件对应于这个数组中的一项。

图4 WXSS的编译过程

在运行时,根据当前的屏幕宽度,计算出1rpx对应多少像素单位,然后将样式信息数组转换成最终的样式添加到页面中。
由于样式在微信客户端存在兼容性问题,为了方便开发者,微信开发者工具提供了上传代码时样式自动补全的功能,利用PostCSS 对WXSS文件进行预处理,自动添加样式前缀。

3 编译JavaScript

微信客户端在运行小程序的逻辑层的时候只需要加载一个JS文件(我们称为app-service.js),而小程序框架允许开发者将 JavaScript 代码写在不同的文件中,所以在代码上传之前,微信开发者工具会对开发者的JS 文件做一些预处理,包括ES6转ES5和代码压缩(开发者可以选择关闭预处理操作),在服务器编译过程将每个JS文件的内容分别包裹在define域中,再按一定的顺序合并成 app-service.js 。其中对于页面JS和app.js需要主动require。

图5 JavaScript的编译过程


3.模拟器

小程序模拟器模拟小程序在微信客户端的逻辑和界面表现,方便开发者实时查看代码效果。由于系统差异以及微信客户端特有的一些交互流程,少部分的API无法在模拟器上进行模拟,但对于绝大部分的 API 均能够在模拟器上呈现出正确的状态。同时微信开发者工具提供多种机型尺寸以及自定义机型尺寸功能,方便开发者进行界面样式的机型适配。

图6 小程序模拟器

2 逻辑层模拟

ios微信客户端上,小程序的JavaScript代码是运行在JavaScriptCore中,在android微信客户端上,小程序的JavaScript代码是通过 X5 JSCore来解析的。而在微信开发者工具上我们采用了一个隐藏着的Webivew来模拟小程序的逻辑运行环境

图7 微信客户端小程序运行环境模型简图

图8 微信开发者工具小程序运行环境模型简图

在微信开发者工具上WebView是一个chrome的 <webview /> 标签。与<iframe />标签不同的是,<webview/>标签是采用独立的线程运行的。
用于模拟小程序逻辑层的<webview/> 加载的链接是

http://127.0.0.1:9973/appservice/appservice

我们在开发者工具底层搭建了一个本地HTTP服务器来处理小程序模拟器的网络请求。其中:

./__asdebug/asdebug.js: 是开发者工具注入的脚本。

./__dev__/WAService.js:是小程序逻辑层基础库。

./util.js、./app.js、./index.js:开发者JS代码。

WebView在请求开发者JS代码时,开发者工具读取JS代码进行必要的预处理后,将处理结果返回,然后由WebView解析执行。虽然开发者工具上是没有对JS代码进行合并的,但是还是按照相同的加载顺序进行解析执行

图9 appservice内容

WebView是一个浏览器环境,而JsCore是一个单纯的脚本解析器,浏览器中的BOM对象无法在JSCore中使用,开发者工具做了一个很巧妙的工作,将开发者的代码包裹在define域的时候,将浏览器的BOM对象局部变量化,从而使得在开发阶段就能发现问题。

图10 BOM对象局部变量化

3 渲染层模拟

微信开发者工具使用chrome的 <webview />标签来加载渲染层页面,每个渲染层WebView加载

http://127.0.0.1:9973/pageframe/pageframe.html

开发者工具底层搭建的HTTP本地服务器在收到这个请求的时候,就会编译WXML文件和WXSS文件,然后将编译结果作为HTTP请求的返回包。当确定加载页面的路径之后,如index页面,开发工具会动态注入如下一段脚本:

// 改变当前webview 的路径,确保之后的图片网络请求能得到正确的相对路径

history.pushState('', '', 'pageframe/index')

// 创建自定义事件,将页面结构生成函数派发出去,由小程序渲染层基础库处理

document.dispatchEvent(new CustomEvent("generateFuncReady", 

   detail: 

     generateFunc: $gwx('./index.wxml')

   

))

// 注入对应页面的样式,这段函数由WXSS编译器生成

setCssToHead()

4 客户端模拟

微信客户端为丰富小程序的功能提供了大量的API。在微信开发者工具上,通过借助BOM(浏览器对象模型)以及node.js访问系统资源的能力,同时模拟客户端的UI和交互流程,使得大部分的API能够正常执行。
借助BOM,如wx.request使用XMLHttpRequest 模拟、wx.connectSocket 使用 WebSocket、wx.startRecord 使用MediaRecorder、wx.playBackgroundAudio 使用 <audio/>标签;
借助node.js,如使用fs实现wx.saveFile、wx.setStorage、wx.chooseImage等API功能。
借助模拟UI和交互流程,实现wx.navigateTo、wx.showToast、wx.openSetting、wx.addCard等。

5 通讯模拟

上文已经叙述了小程序的逻辑层、渲染层以及客户端在微信开发者工具上的模拟实现,除此之外,我们需要一个有效的通讯方案使得小程序的逻辑层、渲染层和客户端之间进行数据交流,才能将这三个部分串联成为一个有机的整体。
微信开发者工具的有一个消息中心底层模块维持着一个WebSocket服务器,小程序的逻辑层的WebView和渲染层页面的WebView通过WebSocket与开发者工具底层建立长连,使用WebSocket的protocol字段来区分Socket的来源。
代码清单2 逻辑层中的消息模块

// <webview/>的userAgent是可定制的
// 通过userAgent中获取开发者工具WebSocket服务器监听的端口
var port = window.navigator.userAgent.match(/port\\/(\\d*)/)[1]
// 通过指定 protocol == 'APPSERVICE' 告知开发者工具这个链接是来自逻辑层
var ws = new WebSocket(`ws://127.0.0.1:$port`, 'APPSERVICE')
ws.onmessage = (evt) => 
  let msg = JSON.parse(evt.data)
  // …处理来自开发者工具的信息
   
// 调用API接口 wx.navigateBack
ws.send(JSON.stringify(
  command: 'APPSERVICE_INVOKE',
  data: 
     api: 'navigateBack',
     args: 
  
))

读《VC++深入了解》前5章小结

第一章 Windows程序内部运行机制

  • API与SDK

API(Application Programming Interface)应用程序编程接口,简称API函数

SDK(Software Development Kit) 软件开发包,即开发所需资源的一个集合,一般包含API函数库、帮助文档、使用手册、辅助工具等资源。

  • 窗口样式,CS_HREDRAW与CS_VREDRAW

水平重画与垂直重画,即如果指定窗口具有这两张样式,则在窗口宽度或高度发生变化时,将重新绘制整个窗口。要去掉style变量所具有的某一样式(如垂直重画),可以编写代码:

style &= ~CS_VREDRAW

  • 创建一个Win32应用程序的步骤
  1. 编写WinMain函数
  2. 设计窗口类(WNDCLASS)
  3. 注册窗口类
  4. 创建窗口
  5. 显示并更新窗口
  6. 编写消息循环
  7. 编写窗口过程函数。窗口过程函数的语法,可通过查看lpfnWndProc成员变量,在这个成员的解释中可查到。

第二章 掌握c++

  • 面向对象 继承
    • public   任何地方都能被访问
    • protected  子类中能被访问,外部不能访问
    • private  只能在自己类中被访问

  类的继承访问特性

基类的访问特性 类的继承特性 子类的访问特性

Public

protected

Private

Public

Public

Protected

No access

Public

protected

Private

Protected

Protected

Protected

No access

Public

protected

Private

Private

Private

Private

No access

 

 

 

 

 

 

 

 

 

 

  • 多态性

  如果父类中的函数前加一个virtual,则子类中有同名函数,调用子类的;子类没有,调用父类的

  • 纯虚函数

  写法:eg: virtual void breathe() = 0 ;

  凡是含有纯虚函数的类叫抽象类。这种类不能声明对象,只是作为基类为派生类服务。在派生类中必须完全实现基类的纯虚函数,

否则派生类也变成抽象类,不能实例化对象

  • 引用和指针变量

  引用和指针变量的内存模型

 

技术分享

  引用不需要内存空间,仅相当于给a取一个别名,a与b指向同一内存块。指针变量本身需要占用一定的内存空间,指针变量的值是所指向变量的内存地址。引用通常用于函数传参。

  • 良好的设计风格

  通常把函数声明放在头文件当中,把函数实现放在源文件当中

  • 防止重复定义

  #ifndef ANIMAL_H_H

  #define ANIMAL_H_H

  ......

  #endif

 

以上是关于深入了解-微信开发者工具的主要内容,如果未能解决你的问题,请参考以下文章

[杂谈]了解一些额外知识,让前端开发锦上添花

前端开发相关汇总

深入了解 JavaScript 内存泄漏

初学web开发需要掌握哪些知识

想学Web前端,你需要了解这些职责和必备技能

微信小程序模块化开发实践