官方网站

什么是 PageSpy?

PageSpy 是一款兼容 Web / 小程序 / React Native / 鸿蒙 App 等平台项目的开源调试平台。基于对原生 API 的封装,它将调用原生方法时的参数进行过滤、转化,整理成一定格式的消息供调试端消费;调试端收到消息数据后,提供类似本地控制台的功能界面将数据呈现出来。

为什么是 PageSpy?

一图胜千言。

何时使用?

任何无法在本地使用控制台调试的场景,都是 PageSpy 可以大显身手的时候! 一起来看下面的几个场景案例:

  • 本地调试 H5、Webview 应用:以往有些产品提供了可以在 H5 上查看信息的面板,但移动端屏幕太小操作不便、显示不友好,以及信息被截断等问题;
  • 远程办公、跨地区协同:传统沟通方式如邮件、电话、视频会议等,沟通效率不高、故障信息不全面,容易误解误判;
  • 用户终端上出现白屏问题:传统定位问题的方式包括数据监控、日志分析等,这些方式依赖排障人员要理解业务需求场景、技术实现;

PageSpy 的目标,就是为包括以上场景的人员提供帮助。

服务部署

使用 Docker 部署

1
docker run -d --restart=always -v ./log:/app/log -v ./data:/app/data -p 6752:6752 --name="pageSpy" ghcr.io/huolalatech/page-spy-web:latest

客户端部署

浏览器

导入 SDK

1
2
3
4
5
6
<!-- PageSpy SDK -->
<script crossorigin="anonymous" src="https://pagespy.jikejishu.com/page-spy/index.min.js"></script>

<!-- 插件(非必须,但建议使用) -->
<script crossorigin="anonymous" src="https://pagespy.jikejishu.com/plugin/data-harbor/index.min.js"></script>
<script crossorigin="anonymous" src="https://pagespy.jikejishu.com/plugin/rrweb/index.min.js"></script>

初始化 PageSpy 和插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
window.$harbor = new DataHarborPlugin();
window.$rrweb = new RRWebPlugin();

[window.$harbor, window.$rrweb].forEach((p) => {
PageSpy.registerPlugin(p);
});

window.$pageSpy = new PageSpy({
// 配置项
api?: string;
clientOrigin?: string;

// "project" is an aggregation of information that can be searched in the room list on the debug side.
// default: 'default'
project?: string;

// "title" is a user-defined parameter that can be used to distinguish the current debugging client,
// and the corresponding information is displayed under the "device id" in each debugging connection panel.
// default: '--'
title?: string;

// Indicates whether the SDK will automatically render the "Circle with Logo on White Background"
// control in the bottom left corner of the client when initiation is complete. If set to false,
// you can call window.$pageSpy.render() to render it manually.
// default: true
autoRender?: boolean;

// Manually specify the scheme of the PageSpy service.
// This works if the SDK can't correctly analyse the scheme, e.g. if PageSpy's browser plugin
// is introduced into the SDK via chrome-extension://xxx/sdk/index.min.js, which will be
// be parsed by the SDK as an invalid "chrome-extension://" and fallback to ["http://", "ws://"].
// - (Default) Pass the value undefined or null: the SDK will parse it automatically;
// - Pass boolean value:
// - true: the SDK will access the PageSpy service via ["https://", "wss://"].
// - false: the SDK will access the PageSpy service via ["http://", "wss://"]
enableSSL?: boolean | null;

// All internal plugins are carried with PageSpy by default out of the box.
// You can disable some plugins as needed.
disabledPlugins?: (InternalPlugins | string)[];

// After adding support for offline replay in PageSpy@1.7.4, the client-integrated SDK can work without
// establishing a connection with the debugger.
// Default value is false, when users set it to other values will enters "offline mode", where PageSpy
// will not create rooms or establish WebSocket connections.
offline?: boolean;

// Customize logo source url.
logo?: string;

// Customize logo style.
logoStyle?: Object;
});

常用 API

更新初始化参数

PageSpy 提供了 Device ID 用于识别设备,同时还提供了 project / title 供开发者在初始化时自定义信息,用于辅助识别客户端。但你可能希望在初始化之后更新这些参数信息,操作方式如下:

1
2
// 调用 updateRoomInfo 可以更新 project / title
window.$pageSpy.updateRoomInfo({ project: "xxx", title: "xxx" });

显示隐藏按钮

1
2
3
4
window.$pageSpy = new PageSpy({
// ... 其他配置参数
autoRender: false,
});

显示

1
window.$pageSpy.render();

隐藏/销毁

1
window.$pageSpy.abort();

常见问题

预览页面 CORS

1
2
3
4
5
6
7
8
9
10
11
server
{
# 设置CORS
# 指定响应资源是否允许与给定的 origin 共享
add_header Access-Control-Allow-Origin '*';
add_header Access-Control-Allow-Credentials 'true';
# 配置允许跨域的请求方法
add_header Access-Control-Allow-Methods 'GET,POST,PUT,DELETE,Options';
# 配置允许跨域的请求头
# add_header Access-Control-Allow-Headers 'Authorization,Content-Type,Accept,Origin,User-Agent,Cache-Control,X-Mx-ReqToken,X-Requested-With';
}