Home

Awesome

WeConsole——功能全面、界面与体验对标 Chrome devtools 的可定制化的跨平台小程序开发调试面板

image image image JavaScript Style Guide

组件效果

主要功能特性

一、背景与简介

在传统的 PC Web 前端开发中,浏览器为开发者提供了体验良好、功能丰富且强大的开发调试工具,比如常见的 Chrome devtools 等,这些调试工具极大的方便了开发者,它们普遍提供查看页面结构、监听网络请求、管理本地数据存储、debugger 代码、使用 Console 快速显示数据等功能。

但是在近几年兴起的微信小程序的前端开发中,却少有类似的体验和功能对标的开发调试工具出现。当然微信小程序的官方也提供了类似的工具,那就是 vConsole,但是相比 PC 端提供的工具来说确实无论是功能和体验都有所欠缺,所以我们开发了 weconsole 来提供更加全面的功能和更好的体验。

基于上述背景,我们(起初)想开发一款运行在微信小程序环境上(目前可运行与多个小程序平台),无论在用户体验还是功能等方面都能媲美 PC 端的前端开发调试工具,当然某些(如 debugger 代码等)受限于技术在当前时期无法实现的功能我们暂且忽略。

我们将这款工具命名为Weimob Console,简写为WeConsole

<img src='./docs/img/wcapi.gif' width="400"></img>

二、安装与使用

<details> <summary>查看步骤:</summary>

1、通过 npm 安装

npm i weconsole -S

2、普通方式安装

此方式会将WeConsole依赖的所有 npm 代码包都自动引入,无需再通过开发者工具进行 npm 编译。

可将 npm 包下载到本地,然后:

3、引用

WeConsole 分为核心组件两部分,使用时需要全部引用后方可使用:

3.1 在app.js文件中引用核心

// NPM方式引用
import 'weconsole/main/init';

// 普通方式引用
import '{复制后的【dist/full】的路径}/main/init';
// NPM方式引用
import 'weconsole/dist/alipay/npm/main/init';

// 普通方式引用
import '{复制后的【dist/alipay/full】的路径}/main/init';
// NPM方式引用
import 'weconsole/dist/xhs/npm/main/init';

// 普通方式引用
import '{复制后的【dist/xhs/full】的路径}/main/init';
// NPM方式引用
import 'weconsole/dist/swan/npm/main/init';

// 普通方式引用
import '{复制后的【dist/swan/full】的路径}/main/init';

引入main/init后,就是默认将 App、Page、Component、Api、Console 全部重写监控!如果想按需重写,可以使用如下方式进行:

import { replace, restore, showWeConsole, hideWeConsole } from '{NPM或复制后的【dist/full】的路径}/main/index';

// scope可选值:App/Page/Component/Console/Api
// 按需替换系统变量或函数以达到监控
replace(scope);

// 可还原
restore(scope);

// 通过show/hide方法控制显示入口图标
showWeConsole();

如果没有显式调用过showWeConsole/hideWeConsole方法,组件第一次初始化时,会根据根据小程序当前状态综合判断入口图标的显示性,这些规则包括:

3.2 在需要的地方引用组件

// NPM方式引用
"usingComponents": {
    "weconsole": "weconsole/subpackage/components/main/index"
}

// 普通方式引用
"usingComponents": {
    "weconsole": "{复制后的【dist/full】的路径}/subpackage/components/main/index"
}
// NPM方式引用
"usingComponents": {
    "weconsole": "weconsole/dist/alipay/npm/subpackage/components/main/index"
}

// 普通方式引用
"usingComponents": {
    "weconsole": "{复制后的【dist/alipay/full】的路径}/subpackage/components/main/index"
}
// NPM方式引用
"usingComponents": {
    "weconsole": "weconsole/dist/xhs/npm/subpackage/components/main/index"
}

// 普通方式引用
"usingComponents": {
    "weconsole": "{复制后的【dist/xhs/full】的路径}/subpackage/components/main/index"
}
// NPM方式引用
"usingComponents": {
    "weconsole": "weconsole/dist/swan/npm/subpackage/components/main/index"
}

// 普通方式引用
"usingComponents": {
    "weconsole": "{复制后的【dist/swan/full】的路径}/subpackage/components/main/index"
}

然后在小程序视图层的xml文件中使用<weconsole>标签进行初始化:

可以使用 weconsole 提供的命令行工具一键批量插入标签,参考 【5、一键注入】

<!-- page/component.wxml -->
<weconsole />

<weconsole>标签支持传入以下属性:

properties: {
    // 组件全屏化后,距离窗口顶部距离
    fullTop: String,
    // 刘海屏机型(如iphone12等)下组件全屏化后,距离窗口顶部距离
    adapFullTop: String,
    // v1.1.0 支持,代表weconsole组件的z-index值
    zIndex: Number,
    // v1.1.0 支持,自定义weconsole图标,传递图片URL
    icon: String,
    // v1.1.0 支持,支持自定义图标样式,传true时同时设置slot="hand"的插槽内容,可定制
    customHand: Boolean
}

4、建议

如果不想将 weconsole 放置在主包中,建议将组件放在分包内使用,利用小程序的 分包异步化 的特性,减少主包大小;

5、一键注入

如果你不想一个个页面的插入<weconsole>标签,或者就想小程序中的所有页面全部插入,那你可以使用 weconsole 提供的命令行工具来完成:

# 安装weconsole后,可使用`weconsole inject`命令进行一键注入

npx weconsole inject ./my-mp-xxx copy replace

weconsole命令可接受的参数及可选值含义如下:

interface InjectConfig {
    /** 要注入的小程序项目目录 */
    projectDir: string;
    /** 如果项目已经被注入过了,是否本次注入要进行替换? */
    replace?: boolean;
    /** 本次注入强行显示weconsole入口图标 */
    forceShow?: boolean;
    /** 注入方式:
     * npm: 以引用npm包的方式注入,但注入后需要开发者工具主动编译才可使用,好处是如果有重复的依赖可以减少代码体积;
     * full: 以全依赖引用的方式注入,无需开发者工具主动编译就可使用,缺点是可能存在依赖包被重复打包代码的问题;
     */
    mode?: 'npm' | 'full';
    /** 注入的小程序项目属于哪个平台?不传时,自动根据目录中的文件特征判断 */
    platform?: 'wx' | 'alipay' | 'xhs' | 'swan';
    /** 注入weconsole标签时传入的fullTop属性值 */
    fullTop?: string;
    /** 注入weconsole标签时传入的adapFullTop属性值 */
    adapFullTop?: string;
    /** 注入weconsole标签时传入的zIndex属性值 */
    zIndex?: number;
    /** 是否在注入时将weconsole的所有JS及组件文件复制到项目根目录? */
    copy?: boolean;
}
</details>

三、功能

<details> <summary>WeConsole 主要包括以下功能:</summary>

1、Console

<!-- ![Console选项卡界面](./docs/img/console.jpg) -->

<img src='./docs/img/console.jpg' width="400"></img>

图 1

<!-- ![Console条目长按操作可选项](./docs/img/console-actions.jpg) -->

<img src='./docs/img/console-actions.jpg' width="400"></img>

图 2

2、Api

<!-- ![Api选项卡界面](./docs/img/api.jpg) -->

<img src='./docs/img/api.jpg' width="400"></img>

图 3

<!-- ![Api条目长按操作可选项](./docs/img/api-actions.jpg) -->

<img src='./docs/img/api-actions.jpg' width="400"></img>

图 4

<!-- ![Api条目详情](./docs/img/api-detail.jpg) -->

<img src='./docs/img/api-detail.jpg' width="400"></img>

图 5

3、Component

<!-- ![Component选项卡界面](./docs/img/component.jpg) -->

<img src='./docs/img/component.jpg' width="400"></img>

图 6

<!-- ![Component实例详情](./docs/img/component-detail.jpg) -->

<img src='./docs/img/component-detail.jpg' width="400"></img>

图 7

4、Storage

<!-- ![Storage选项卡界面](./docs/img/storage.jpg) -->

<img src='./docs/img/storage.jpg' width="400"></img>

图 8

<!-- ![Storage详情](./docs/img/storage-detail.jpg) -->

<img src='./docs/img/storage-detail.jpg' width="400"></img>

图 9

5、其他

import { setUIRunConfig } from 'xxx/weconsole/main/index.js';

setUIRunConfig({
    customActions: [
        {
            id: 'test1',
            title: '显示文本',
            autoCase: 'show',
            cases: [
                {
                    id: 'show',
                    button: '查看',
                    showMode: WcCustomActionShowMode.text,
                    handler(): string {
                        return '测试文本';
                    }
                },
                {
                    id: 'show2',
                    button: '查看2',
                    showMode: WcCustomActionShowMode.text,
                    handler(): string {
                        return '测试文本2';
                    }
                }
            ]
        },
        {
            id: 'test2',
            title: '显示JSON',
            autoCase: 'show',
            cases: [
                {
                    id: 'show',
                    button: '查看',
                    showMode: WcCustomActionShowMode.json,
                    handler() {
                        return wx;
                    }
                }
            ]
        },
        {
            id: 'test3',
            title: '显示表格',
            autoCase: 'show',
            cases: [
                {
                    id: 'show',
                    button: '查看',
                    showMode: WcCustomActionShowMode.grid,
                    handler(): WcCustomActionGrid {
                        return {
                            cols: [
                                {
                                    title: 'Id',
                                    field: 'id',
                                    width: 30
                                },
                                {
                                    title: 'Name',
                                    field: 'name',
                                    width: 70
                                }
                            ],
                            data: [
                                {
                                    id: 1,
                                    name: 'Tom'
                                },
                                {
                                    id: 2,
                                    name: 'Alice'
                                }
                            ]
                        };
                    }
                }
            ]
        }
    ]
});
<!-- ![Other选项卡界面](./docs/img/other.jpg) -->

<img src='./docs/img/other.jpg' width="400"></img>

图 10

<!-- ![Other 定制化案例](./docs/img/other-demos.jpg) -->

<img src='./docs/img/other-demos.jpg' width="400"></img>

图 10

</details>

四、API

<details> <summary>主要暴露以下API:</summary>

通过以下方式使用 API

import { showWeConsole, ... } from 'weconsole';
showWeConsole();

replace(scope:'App'|'Page'|'Component'|'Api'|'Console')

替换系统变量或函数以达到监控,底层控制全局仅替换一次

restore(scope:'App'|'Page'|'Component'|'Api'|'Console')

还原被替换的系统变量或函数,还原后界面将不在显示相关数据

showWeConsole()

显示WeConsole入口图标

hideWeConsole()

隐藏WeConsole入口图标

setUIConfig(config: Partial<MpUIConfig>)

设置WeConsole组件内的相关配置,可接受的配置项及含义如下:

interface MpUIConfig {
    /** 监控小程序API数据后,使用该选项进行该数据的分类值计算,计算后的结果显示在界面上 */
    apiCategoryGetter?: MpProductCategoryMap | MpProductCategoryGetter;
    /** 监控Console数据后,使用该选项进行该数据的分类值计算,计算后的结果显示在界面上 */
    consoleCategoryGetter?: MpProductCategoryMap | MpProductCategoryGetter;
    /** Other内置信息中获取当前页面实例时执行的方法 */
    currentPageGetter?: () => MpView;
    /** API选项卡下显示的数据分类列表,all、mark、other 分类固定存在 */
    apiCategoryList?: Array<string | MpNameValue<string>>;
    /** 复制策略,传入复制数据,可通过数据的type字段判断数据哪种类型,比如api/console */
    copyPolicy?: MpProductCopyPolicy;
    /** 定制化列表 */
    customActions?: WcCustomAction[];
    /** 默认的api分类值 */
    apiDefaultCategoryValue?: string;
    /** 默认的console分类值 */
    consoleDefaultCategoryValue?: string;
    /** 不监控这些API,也就是说这些API调用后不会在【API】选项卡中显示 */
    ignoreHookApiNames?: string[];
    /** 只监控这些API,也就是除了这些API以外的其他调用都不会在【API】选项卡中显示 */
    onlyHookApiNames?: string[];
    /** 全局对象,如果你的小程序存在沙盒环境,请务必传递一个可供全局存储数据的单例对象 */
    globalObject?: any;
}

// 配置项的详细types请参考源码目录:src/types

addCustomAction(action: WcCustomAction)

添加一个定制化项目;当你添加的项目中需要显示你自己的组件时:

removeCustomAction(actionId: string)

根据 ID 删除一个定制化项目

getWcControlMpViewInstances():any[]

获取小程序内 weconsole 已经监控到的所有的 App/Page/Component 实例

log(type = "log", ...args)

因为 console 被重写,当你想使用最原始的 console 方法时,可以通过该方式,type 就是 console 的方法名

on/once/off/emit

提供一个事件总线功能,全局事件及相关函数定义如下:

const enum WeConsoleEvents {
    /**UIConfig对象发生变化时 */
    WcUIConfigChange = 'WcUIConfigChange',
    /**入口图标显示性发生变化时 */
    WcVisableChange = 'WcVisableChange',
    /**CanvasContext准备好时,CanvasContext用于JSON树组件的界面文字宽度计算 */
    WcCanvasContextReady = 'WcCanvasContextReady',
    /**CanvasContext销毁时 */
    WcCanvasContextDestory = 'WcCanvasContextDestory',
    /**主组件的宽高发生变化时 */
    WcMainComponentSizeChange = 'WcMainComponentSizeChange'
}

interface IEventEmitter<T = any> {
    on(type: string, handler: EventHandler<T>);
    once(type: string, handler: EventHandler<T>);
    off(type: string, handler?: EventHandler<T>);
    emit(type: string, data?: T);
}
</details>

五、后续规划

六、贡献流程

请阅读 贡献流程 文档来参与项目的迭代与开发,我们将会非常感谢您的付出。

七、License

WeConsole 使用 MIT 协议.

八、声明

生产环境请谨慎使用。

九、更新记录

<details> <summary>更新记录:</summary> </details>