spy-client 2.1.7 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -11
- package/dist/spy-client-basic.esm.js +5 -2
- package/dist/spy-client-basic.iife.js +5 -2
- package/dist/spy-client-basic.iife.min.js +1 -1
- package/dist/spy-client-basic.js +5 -2
- package/dist/spy-client-basic.min.js +1 -1
- package/dist/spy-client-basic.mjs +5 -2
- package/dist/spy-client.esm.js +19 -11
- package/dist/spy-client.iife.js +19 -11
- package/dist/spy-client.iife.min.js +1 -1
- package/dist/spy-client.js +19 -11
- package/dist/spy-client.min.js +1 -1
- package/dist/spy-client.mjs +19 -11
- package/dist/spy-head.js +15 -10
- package/dist/spy-head.min.js +1 -1
- package/example/index.html +2 -0
- package/package.json +1 -1
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/src/head/base.ts +0 -69
- package/src/head/error.ts +0 -118
- package/src/head/observer.ts +0 -40
- package/src/head/readme.md +0 -1
- package/src/head/whitescreen.ts +0 -105
- package/src/lib/data.ts +0 -14
- package/src/lib/huffman.ts +0 -307
- package/src/lib/interface.ts +0 -331
- package/src/lib/spyHeadInterface.ts +0 -40
- package/src/lib/util.ts +0 -101
- package/src/module/fid.ts +0 -56
- package/src/module/layoutShift.ts +0 -71
- package/src/module/lcp.ts +0 -63
- package/src/module/longtask.ts +0 -193
- package/src/module/memory.ts +0 -43
- package/src/module/navigatorInfo.ts +0 -61
- package/src/module/resource.ts +0 -433
- package/src/module/timing.ts +0 -75
- package/src/module/tti.ts +0 -139
- package/src/spy-client-basic.ts +0 -387
- package/src/spy-client.ts +0 -198
- package/src/spy-head.ts +0 -31
- package/src/spy-local-cache.ts +0 -478
- package/src/types/globals.d.ts +0 -93
package/src/lib/huffman.ts
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Huffman
|
|
3
|
-
* @author kaivean
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
赫夫曼编码
|
|
9
|
-
基本介绍
|
|
10
|
-
|
|
11
|
-
1.赫夫曼编码也翻译为 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式, 属于一种程序算法
|
|
12
|
-
赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。
|
|
13
|
-
|
|
14
|
-
2.赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在20%~90%之间
|
|
15
|
-
赫夫曼码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,称之为最佳编码
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
class HuffmanNode {
|
|
22
|
-
data;// 存放数据(字符本身),比如 'a' => 97, ' '=>32
|
|
23
|
-
weight;// 权值,表示字符串出现的次数
|
|
24
|
-
left: HuffmanNode;
|
|
25
|
-
right: HuffmanNode;
|
|
26
|
-
constructor(data: any, weight: number) {
|
|
27
|
-
this.data = data;
|
|
28
|
-
this.weight = weight;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 前序遍历
|
|
32
|
-
preOrder(arr: any) {
|
|
33
|
-
arr.push(this);
|
|
34
|
-
if (this.left) {
|
|
35
|
-
this.left.preOrder(arr);
|
|
36
|
-
}
|
|
37
|
-
if (this.right) {
|
|
38
|
-
this.right.preOrder(arr);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
* @param {接受字符数组} bytes
|
|
47
|
-
* @return 返回的就是list形式
|
|
48
|
-
*/
|
|
49
|
-
function getNodes(bytes: any[]): HuffmanNode[] {
|
|
50
|
-
// 创建一个list
|
|
51
|
-
let list: HuffmanNode[] = [];
|
|
52
|
-
// counts 统计每一个byte出现的次数
|
|
53
|
-
let counts: any = {};
|
|
54
|
-
for (let b of bytes) {
|
|
55
|
-
let count = counts[b]; // map还没有这个字符数据
|
|
56
|
-
if (count == null) {
|
|
57
|
-
counts[b] = 1;
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
counts[b]++;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (const [key, value] of Object.entries(counts)) {
|
|
65
|
-
list.push(new HuffmanNode(key, value as number));
|
|
66
|
-
}
|
|
67
|
-
return list;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// 通过list创建赫夫曼树
|
|
72
|
-
function createHuffmanTree(nodes: HuffmanNode[]): HuffmanNode | undefined {
|
|
73
|
-
const compareFun = function (a: HuffmanNode, b: HuffmanNode) {
|
|
74
|
-
return a.weight - b.weight;
|
|
75
|
-
};
|
|
76
|
-
while (nodes.length > 1) {
|
|
77
|
-
// 排序,从小到大
|
|
78
|
-
nodes.sort(compareFun);
|
|
79
|
-
// 取出第一颗最小的二叉树
|
|
80
|
-
let leftNode = nodes.shift();
|
|
81
|
-
let rightNode = nodes.shift();
|
|
82
|
-
if (leftNode && rightNode) {
|
|
83
|
-
// 创建一个新的二叉树,它的根节点,没有data,只有权值
|
|
84
|
-
let parent = new HuffmanNode(null, leftNode.weight + rightNode.weight);
|
|
85
|
-
parent.left = leftNode;
|
|
86
|
-
parent.right = rightNode;
|
|
87
|
-
|
|
88
|
-
// 将新的二叉树,加入到nodes
|
|
89
|
-
nodes.unshift(parent);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
// nodes最后的节点,就是根节点
|
|
94
|
-
return nodes.shift();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 生成赫夫曼树对应的赫夫曼编码表
|
|
98
|
-
function getHuffmanCodes(root: any) {
|
|
99
|
-
if (root == null) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
// 生成赫夫曼树对应的赫夫曼编码表
|
|
103
|
-
// 思路
|
|
104
|
-
// 1.将赫夫曼编码表存放在map里面
|
|
105
|
-
// 2.在生成赫夫曼编码表时,需要拼接路径,定义一个数组string,存储某个叶子节点的路径
|
|
106
|
-
|
|
107
|
-
let huffmanCodes: any = {};
|
|
108
|
-
let strings: any[] = [];
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* 将传入的node节点的所有叶子节点的赫夫曼编码得到,并放入到huffmanCodes集合中
|
|
112
|
-
* @param {传入节点} node
|
|
113
|
-
* @param {路径:左子节点是0,右子节点是1} code
|
|
114
|
-
* @param {用于拼接路径} string
|
|
115
|
-
*/
|
|
116
|
-
function getCodes(node: HuffmanNode, code: string, strs: string[]) {
|
|
117
|
-
let string2 = ([] as string[]).concat(strs);
|
|
118
|
-
// 将code加入到string中
|
|
119
|
-
string2.push(code);
|
|
120
|
-
if (node != null) { // 如果node == null不处理
|
|
121
|
-
// 判断当前node是叶子节点还是非叶子节点
|
|
122
|
-
if (node.data == null) { // 非叶子节点
|
|
123
|
-
// 递归处理
|
|
124
|
-
// 向左递归
|
|
125
|
-
getCodes(node.left, '0', string2);
|
|
126
|
-
// 向右递归
|
|
127
|
-
getCodes(node.right, '1', string2);
|
|
128
|
-
}
|
|
129
|
-
else { // 说明是一个叶子节点
|
|
130
|
-
// 就表示找到了某个叶子节点的最后
|
|
131
|
-
huffmanCodes[node.data] = string2.join('');
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
getCodes(root, '', strings);
|
|
136
|
-
return huffmanCodes;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 编写一个方法,将字符串对应的bytes数组,通过生成的赫夫曼编码表,返回一个赫夫曼编码压缩后的byte数组
|
|
142
|
-
* @param {原始的字符串对应的bytes数组} bytes
|
|
143
|
-
* @param {生成的赫夫曼编码表} huffmanCodes
|
|
144
|
-
* @return 返回的是字符串对应的一个byte数组
|
|
145
|
-
*/
|
|
146
|
-
function zip(bytes: number[], huffmanCodes: any) {
|
|
147
|
-
// 1.利用huffmanCodes将bytes转成赫夫曼编码对应的字符串
|
|
148
|
-
let string = [];
|
|
149
|
-
// 遍历数组
|
|
150
|
-
for (let b of bytes) {
|
|
151
|
-
string.push(huffmanCodes[b]);
|
|
152
|
-
}
|
|
153
|
-
return string;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function huffStringToByte(strs: string[]) {
|
|
157
|
-
// 计算赫夫曼编码字符串的长度
|
|
158
|
-
let str = strs.join('');
|
|
159
|
-
let len = Math.ceil(str.length / 8);
|
|
160
|
-
// 创建存储压缩后的byte数组
|
|
161
|
-
let huffmanCodeByte = new Array(len + 1);
|
|
162
|
-
let index = 0;
|
|
163
|
-
let strByte: string = ''; // 记录是第几个byte
|
|
164
|
-
for (let i = 0; i < str.length; i += 8) {
|
|
165
|
-
strByte = str.substring(i, i + 8);
|
|
166
|
-
// 将strByte转成一个byte,放入huffmanCodeByte
|
|
167
|
-
huffmanCodeByte[index] = parseInt(strByte, 2);
|
|
168
|
-
index++;
|
|
169
|
-
}
|
|
170
|
-
// 记录最后一位二进制码的长度,因为,比如最后一位二进制strByte为00101时,
|
|
171
|
-
// parseInt(strByte, 2)后等于5,前面的两个00已经丢失,所以必须记录长度,以便解码时补足前面的0
|
|
172
|
-
huffmanCodeByte[index] = strByte.length;
|
|
173
|
-
return huffmanCodeByte;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// 使用一个方法,封装前面的方法,便于调用
|
|
177
|
-
/**
|
|
178
|
-
*
|
|
179
|
-
* @param {原始的字符串对应的字节数组} bytes
|
|
180
|
-
* @returns 是经过赫夫曼编码处理后,压缩后的字节数组
|
|
181
|
-
*
|
|
182
|
-
*/
|
|
183
|
-
function huffmanZip(bytes: any[]) {
|
|
184
|
-
// 1.生成节点数组
|
|
185
|
-
let nodes = getNodes(bytes);
|
|
186
|
-
// 2.根据节点数组创建赫夫曼树
|
|
187
|
-
let root = createHuffmanTree(nodes);
|
|
188
|
-
// 3.根据赫夫曼树生成赫夫曼编码
|
|
189
|
-
let hufumanCodes = getHuffmanCodes(root);
|
|
190
|
-
// 4.根据生成的赫夫曼编码生成压缩后的赫夫曼编码字节数组
|
|
191
|
-
let hufumanStrArr = zip(bytes, hufumanCodes);
|
|
192
|
-
let hufumanByteArr = huffStringToByte(hufumanStrArr);
|
|
193
|
-
|
|
194
|
-
return {result: hufumanByteArr, codes: hufumanCodes};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// 完成数据的解压
|
|
198
|
-
// 思路
|
|
199
|
-
// 1.将huffmanBytesArr先转成赫夫曼编码对应的二进制字符串
|
|
200
|
-
// 2.将赫夫曼编码对应的二进制的字符串转成赫夫曼编码字符串
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
*
|
|
204
|
-
* @param {表示是否需要补高位,如果是true,表示需要,如果是false,表示不需要,如果是最后一个字节不需要补高位} flag
|
|
205
|
-
* @param {传入的byte} byte
|
|
206
|
-
* @returns 是byte对应的二进制字符串
|
|
207
|
-
*/
|
|
208
|
-
function huffByteToString(flag: boolean, byte: number) {
|
|
209
|
-
// 如果是
|
|
210
|
-
if (flag) {
|
|
211
|
-
byte |= 256;
|
|
212
|
-
}
|
|
213
|
-
let str = Number(byte).toString(2);
|
|
214
|
-
if (flag) {
|
|
215
|
-
return str.substring(str.length - 8);
|
|
216
|
-
}
|
|
217
|
-
return str;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* 编写一份方法,完成对压缩数据的解码
|
|
223
|
-
* @param {赫夫曼编码表} huffmanCodes
|
|
224
|
-
* @param {赫夫曼编码得到的二进制数组} huffmanBytes
|
|
225
|
-
*/
|
|
226
|
-
function decode(huffmanCodes: {[key: string]: string}, huffmanBytes: number[]) {
|
|
227
|
-
// 1.先得到二进制字符串 形式11001111111011......
|
|
228
|
-
let heffmanStrArr = [];
|
|
229
|
-
for (let i = 0; i < huffmanBytes.length - 1; i++) {
|
|
230
|
-
// 判断是不是最后一个字节
|
|
231
|
-
let flag = (i !== huffmanBytes.length - 2);
|
|
232
|
-
heffmanStrArr.push(huffByteToString(flag, huffmanBytes[i]));
|
|
233
|
-
}
|
|
234
|
-
// 最后一位记录的是最后一位二进制字符串的长度,该长度主要用于补足最后一位丢失的0,所以要单独处理,
|
|
235
|
-
let lastByteStr = heffmanStrArr[heffmanStrArr.length - 1];
|
|
236
|
-
let lastByteLength = huffmanBytes[huffmanBytes.length - 1];
|
|
237
|
-
lastByteStr = '00000000'.substring(8 - (lastByteLength - lastByteStr.length)) + lastByteStr;
|
|
238
|
-
heffmanStrArr[heffmanStrArr.length - 1] = lastByteStr;
|
|
239
|
-
|
|
240
|
-
// 把赫夫曼编码表进行调换
|
|
241
|
-
let map: {[key: string]: string} = {};
|
|
242
|
-
for (const [key, value] of Object.entries(huffmanCodes)) {
|
|
243
|
-
map[value] = key;
|
|
244
|
-
}
|
|
245
|
-
let heffmanStr = heffmanStrArr.join('');
|
|
246
|
-
let list = [];
|
|
247
|
-
let len = heffmanStr.length;
|
|
248
|
-
for (let i = 0; i < len;) {
|
|
249
|
-
let count = 1;
|
|
250
|
-
let flag = true;
|
|
251
|
-
let b: string | null = null;
|
|
252
|
-
while (flag && i + count <= len) {
|
|
253
|
-
// 取出一个1或0
|
|
254
|
-
// i不动,count移动,直到匹配到一个字符
|
|
255
|
-
let key = heffmanStr.substring(i, i + count);
|
|
256
|
-
if (key === '') {
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
b = map[key];
|
|
260
|
-
if (!b) { // 没有匹配到
|
|
261
|
-
count++;
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
// 匹配到
|
|
265
|
-
flag = false;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
list.push(parseInt(b as string, 10));
|
|
269
|
-
i += count;
|
|
270
|
-
}
|
|
271
|
-
// 当for循环结束后,list中就存放了所有的字符
|
|
272
|
-
|
|
273
|
-
return list;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
// js byte[] 和string 相互转换 UTF-8
|
|
278
|
-
function stringToByte(str: string): number[] {
|
|
279
|
-
let bytes = [];
|
|
280
|
-
for (let index = 0; index < str.length; index++) {
|
|
281
|
-
bytes.push(str.charCodeAt(index));
|
|
282
|
-
}
|
|
283
|
-
return bytes;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function byteToString(arr: number[]): string {
|
|
287
|
-
let data = '';
|
|
288
|
-
for (const code of arr) {
|
|
289
|
-
data += String.fromCharCode(code);
|
|
290
|
-
}
|
|
291
|
-
return data;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
export function huffmanEncode(str: string) {
|
|
295
|
-
let bytes = stringToByte(str);
|
|
296
|
-
let {result, codes} = huffmanZip(bytes);
|
|
297
|
-
return {
|
|
298
|
-
codes,
|
|
299
|
-
result: byteToString(result),
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export function huffmanDecode(codes: any, str: string) {
|
|
304
|
-
let bytes = stringToByte(str);
|
|
305
|
-
const data = decode(codes, bytes);
|
|
306
|
-
return byteToString(data);
|
|
307
|
-
}
|
package/src/lib/interface.ts
DELETED
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
export interface SpyClientOption {
|
|
2
|
-
/**
|
|
3
|
-
* 模块ID
|
|
4
|
-
*/
|
|
5
|
-
pid: string;
|
|
6
|
-
|
|
7
|
-
// 日志ID
|
|
8
|
-
/**
|
|
9
|
-
* 日志ID
|
|
10
|
-
*/
|
|
11
|
-
lid?: string;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 全局抽样配置,默认是 1,取值从[0, 1]
|
|
15
|
-
*/
|
|
16
|
-
sample?: number;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 是否校验发送字段符合规范,默认是 true
|
|
20
|
-
*/
|
|
21
|
-
check?: boolean;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 日志服务器,默认是webb服务器,尾部需要加?
|
|
25
|
-
*/
|
|
26
|
-
logServer?: string;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 本地日志cache对象,是指独立的spy-local-cache模块实例
|
|
30
|
-
*/
|
|
31
|
-
localCache?: any;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class Module {
|
|
35
|
-
// public constructor() {}
|
|
36
|
-
// [propName: string]: listenCallback[],
|
|
37
|
-
// init: () => void;
|
|
38
|
-
load?: () => void;
|
|
39
|
-
leave?: () => void;
|
|
40
|
-
destroy?: () => void;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface FIDMetric {
|
|
44
|
-
// First Input Delay https://web.dev/fid/
|
|
45
|
-
// 首次输入延迟
|
|
46
|
-
fid: number;
|
|
47
|
-
}
|
|
48
|
-
export type FIDCB = (metric: FIDMetric) => void;
|
|
49
|
-
|
|
50
|
-
export interface LCPMetric {
|
|
51
|
-
// Largest Contentful Paint https://web.dev/lcp/
|
|
52
|
-
// 在onload时间内最大块内容绘制完成时间
|
|
53
|
-
lcp: number;
|
|
54
|
-
}
|
|
55
|
-
export type LCPCB = (metric: LCPMetric) => void;
|
|
56
|
-
|
|
57
|
-
export enum ResType {
|
|
58
|
-
JS = 'js',
|
|
59
|
-
CSS = 'css',
|
|
60
|
-
IMG = 'img',
|
|
61
|
-
FONT = 'font',
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface ResourceMetric {
|
|
65
|
-
// 页面整体大小:包括主文档、所有JS、CSS、Img、Font,单位KB
|
|
66
|
-
allSize: number;
|
|
67
|
-
// 主文档大小 KB
|
|
68
|
-
docSize: number;
|
|
69
|
-
// 主文档的响应header的大小,包含cookie等 KB
|
|
70
|
-
headerSize: number;
|
|
71
|
-
|
|
72
|
-
// js外链的个数
|
|
73
|
-
jsNum: number;
|
|
74
|
-
cssNum: number;
|
|
75
|
-
imgNum: number;
|
|
76
|
-
fontNum: number;
|
|
77
|
-
|
|
78
|
-
// 所有JS外链的大小
|
|
79
|
-
jsSize: number;
|
|
80
|
-
cssSize: number;
|
|
81
|
-
imgSize: number;
|
|
82
|
-
fontSize: number;
|
|
83
|
-
|
|
84
|
-
// 页面整体网络传输大小,通常来说资源有了缓存,传输大小就为0,另外有Gzip的话,传输大小相比资源本身大小也要小很多
|
|
85
|
-
allTransferSize: number;
|
|
86
|
-
// 主文档网络传输大小
|
|
87
|
-
docTransferSize: number;
|
|
88
|
-
// 所有JS外链的传输大小
|
|
89
|
-
jsTransferSize: number;
|
|
90
|
-
cssTransferSize: number;
|
|
91
|
-
imgTransferSize: number;
|
|
92
|
-
fontTransferSize: number;
|
|
93
|
-
|
|
94
|
-
jsDuration: number;
|
|
95
|
-
cssDuration: number;
|
|
96
|
-
imgDuration: number;
|
|
97
|
-
fontDuration: number;
|
|
98
|
-
|
|
99
|
-
// js cache率
|
|
100
|
-
jsCacheRate: number;
|
|
101
|
-
cssCacheRate: number;
|
|
102
|
-
imgCacheRate: number;
|
|
103
|
-
};
|
|
104
|
-
export interface ResourceHostMetric {
|
|
105
|
-
[host: string]: {
|
|
106
|
-
hostNum: number;
|
|
107
|
-
hostSize: number;
|
|
108
|
-
hostTransferSize: number;
|
|
109
|
-
hostDuration: number;
|
|
110
|
-
hostCacheRate: number;
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
export type ResourceCB = (metric: ResourceMetric, hostMetric: ResourceHostMetric) => void;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
export interface ResourceErrorInfo {
|
|
117
|
-
// 发生异常的资源链接
|
|
118
|
-
msg: string;
|
|
119
|
-
// 发生异常的资源元素的xpath信息,一直到body
|
|
120
|
-
xpath: string;
|
|
121
|
-
// 资源host
|
|
122
|
-
host: string;
|
|
123
|
-
// 资源类型
|
|
124
|
-
type: string;
|
|
125
|
-
// 资源耗时
|
|
126
|
-
dur?: number;
|
|
127
|
-
}
|
|
128
|
-
export type ResourceErrorCB = (info: ResourceErrorInfo) => void;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
export interface TimingMetric {
|
|
132
|
-
// dns解析
|
|
133
|
-
dns: number;
|
|
134
|
-
// tcp链接
|
|
135
|
-
tcp: number;
|
|
136
|
-
// 主文档请求
|
|
137
|
-
request: number;
|
|
138
|
-
// 主文档响应时间
|
|
139
|
-
response: number;
|
|
140
|
-
// DOM解析时间:Dom解析开始到结束时间
|
|
141
|
-
// 这是从页面部分数据返回,浏览器开始解析doc元素到最底部的script脚本解析执行完成
|
|
142
|
-
// 脚本里触发的异步方法或绑定了更靠后的事件,不再纳入范围内
|
|
143
|
-
parseHtml: number;
|
|
144
|
-
// DOM解析完成总时间:页面开始加载到Dom解析结束
|
|
145
|
-
// 很多事件绑定是在domContentLoaded事件里的,所以等其结束,一般页面元素的事件绑定好了,用户可以正确交互
|
|
146
|
-
// 当然存在在该加载事件之后绑定元素事件情况,但不再此考虑范围内
|
|
147
|
-
domReady: number;
|
|
148
|
-
// 处理所有注册的load事件函数的时间
|
|
149
|
-
loadEventHandle: number;
|
|
150
|
-
// onload完成时间
|
|
151
|
-
// 基本该做的都做完,资源也都加载完成了
|
|
152
|
-
// 当然在onload事件处理函数里启动了异步方法,不再纳入范围内
|
|
153
|
-
load: number;
|
|
154
|
-
// first-paint https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
|
|
155
|
-
fp?: number;
|
|
156
|
-
// first-contentful-paint https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
|
|
157
|
-
fcp?: number;
|
|
158
|
-
// T7内核计算的首次绘制, 单位ms
|
|
159
|
-
t7FirstPaint?: number;
|
|
160
|
-
// T7内核计算的首屏时间, 单位ms
|
|
161
|
-
t7FirstScreen?: number;
|
|
162
|
-
}
|
|
163
|
-
export type TimingCB = (metric: TimingMetric) => void;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
export interface TTIMetric {
|
|
167
|
-
// Time to Interactive https://web.dev/tti/
|
|
168
|
-
// 用户可完全交互时间
|
|
169
|
-
tti: number;
|
|
170
|
-
}
|
|
171
|
-
export type TTICB = (metric: TTIMetric) => void;
|
|
172
|
-
|
|
173
|
-
export interface TTIOption {
|
|
174
|
-
// TTI定义里的quiet window,默认是5000 单位ms
|
|
175
|
-
interval?: number;
|
|
176
|
-
// TTI要求在quiet window内,没有任何网络请求,但有一些不会影响页面的请求,比如日志请求,最好过滤掉,避免一直hang在quiet window
|
|
177
|
-
// 默认下,排除掉所有gif请求
|
|
178
|
-
filterRequest?: (entry: PerformanceEntry) => boolean;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export interface LayoutShiftMetric {
|
|
182
|
-
// Cumulative Layout Shift定义 https://web.dev/cls/
|
|
183
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内的 Cumulative Layout Shift
|
|
184
|
-
layoutShift: number;
|
|
185
|
-
}
|
|
186
|
-
export type LayoutShiftCB = (metric: LayoutShiftMetric) => void;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
export interface MemoryMetric {
|
|
190
|
-
// 使用内存, 单位KB
|
|
191
|
-
usedJSHeapSize: number;
|
|
192
|
-
// 分配给页面的内存,单位KB
|
|
193
|
-
totalJSHeapSize: number;
|
|
194
|
-
// 内存限制,单位KB
|
|
195
|
-
jsHeapSizeLimit: number;
|
|
196
|
-
// 内存使用率百分比 = 100 * usedJSHeapSize / totalJSHeapSize
|
|
197
|
-
usedJSHeapRate: number;
|
|
198
|
-
}
|
|
199
|
-
export type MemoryCB = (metric: MemoryMetric) => void;
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
export interface NavigatorInfoMetric {
|
|
203
|
-
// 网络下载速度 https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/connection
|
|
204
|
-
downlink?: number;
|
|
205
|
-
// 网络类型
|
|
206
|
-
effectiveType?: '2g' | '3g' | '4g' | 'slow-2g';
|
|
207
|
-
// 估算的往返时间
|
|
208
|
-
rtt?: number;
|
|
209
|
-
// 数据保护模式
|
|
210
|
-
saveData?: boolean;
|
|
211
|
-
// 设备内存 https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory
|
|
212
|
-
deviceMemory?: number;
|
|
213
|
-
// 设备逻辑核数 https://developer.mozilla.org/en-US/docs/Web/API/NavigatorConcurrentHardware/hardwareConcurrency
|
|
214
|
-
hardwareConcurrency?: number;
|
|
215
|
-
}
|
|
216
|
-
export type NavigatorInfoCB = (metric: NavigatorInfoMetric) => void;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
export interface FSPLongtaskMetric {
|
|
220
|
-
// 在T7内核首屏时间内, 每个longtask的时间总和
|
|
221
|
-
fspLongtaskTime: number;
|
|
222
|
-
// 在T7内核首屏时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
|
|
223
|
-
// Total Blocking Time定义:
|
|
224
|
-
fspTBT: number;
|
|
225
|
-
// T7内核首屏时间
|
|
226
|
-
fspTotalTime: number;
|
|
227
|
-
// 在T7内核首屏时间内, Longtask率 = 100 * fspLongtaskTime / fspTotalTime
|
|
228
|
-
fspLongtaskRate: number;
|
|
229
|
-
// 在T7内核首屏时间内的Longtask数量
|
|
230
|
-
fspLongtaskNum: number;
|
|
231
|
-
}
|
|
232
|
-
export type FSPLongtaskCB = (metric: FSPLongtaskMetric) => void;
|
|
233
|
-
|
|
234
|
-
export interface LCPLongtaskMetric {
|
|
235
|
-
// 在Largest Contentful Paint时间内, 每个longtask的时间总和
|
|
236
|
-
lcpLongtaskTime: number;
|
|
237
|
-
// 在Largest Contentful Paint时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
|
|
238
|
-
lcpTBT: number;
|
|
239
|
-
// Largest Contentful Paint时间
|
|
240
|
-
lcpTotalTime: number;
|
|
241
|
-
// 在Largest Contentful Paint时间内, Longtask率 = 100 * lcpLongtaskTime / lcpTotalTime
|
|
242
|
-
lcpLongtaskRate: number;
|
|
243
|
-
// 在Largest Contentful Paint时间内的Longtask数量
|
|
244
|
-
lcpLongtaskNum: number;
|
|
245
|
-
}
|
|
246
|
-
export type LCPLongtaskCB = (metric: LCPLongtaskMetric) => void;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
export interface LoadLongtaskMetric {
|
|
250
|
-
// 在onload即页面加载完成时间内, 每个longtask的时间总和
|
|
251
|
-
loadLongtaskTime: number;
|
|
252
|
-
// 在onload即页面加载完成时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
|
|
253
|
-
loadTBT: number;
|
|
254
|
-
// onload即页面加载完成时间
|
|
255
|
-
loadTotalTime: number;
|
|
256
|
-
// 在onload即页面加载完成时间内, Longtask率 = 100 * loadLongtaskTime / loadTotalTime
|
|
257
|
-
loadLongtaskRate: number;
|
|
258
|
-
// 在onload即页面加载完成时间内的Longtask数量
|
|
259
|
-
loadLongtaskNum: number;
|
|
260
|
-
}
|
|
261
|
-
export type LoadLongtaskCB = (metric: LoadLongtaskMetric) => void;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
export interface PageLongtaskMetric {
|
|
265
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内, 每个longtask的时间总和
|
|
266
|
-
pageLongtaskTime: number;
|
|
267
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
|
|
268
|
-
pageTBT: number;
|
|
269
|
-
// 开始加载页面到第一次离开页面(隐藏或点出)时间
|
|
270
|
-
pageTotalTime: number;
|
|
271
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内, Longtask率 = 100 * pageLongtaskTime / pageTotalTime
|
|
272
|
-
pageLongtaskRate: number;
|
|
273
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内的Longtask数量
|
|
274
|
-
pageLongtaskNum: number;
|
|
275
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的longtask的时间总和
|
|
276
|
-
pageIframeLongtaskTime: number;
|
|
277
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的Longtask率 = 100 * pageIframeLongtaskTime / pageTotalTime
|
|
278
|
-
pageIframeLongtaskRate: number;
|
|
279
|
-
// 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的Longtask数量
|
|
280
|
-
pageIframeLongtaskNum: number;
|
|
281
|
-
}
|
|
282
|
-
export type PageLongtaskCB = (metric: PageLongtaskMetric) => void;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
export interface ResOption {
|
|
286
|
-
ignorePaths?: string[];
|
|
287
|
-
trigger?: 'load' | 'leave';
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export interface BigImgOption {
|
|
291
|
-
/**
|
|
292
|
-
* 体积大于该阈值,就认为是大图,默认150,单位是kb
|
|
293
|
-
*/
|
|
294
|
-
maxSize?: number;
|
|
295
|
-
/**
|
|
296
|
-
* 忽略指定path的资源
|
|
297
|
-
*/
|
|
298
|
-
ignorePaths?: string[];
|
|
299
|
-
/**
|
|
300
|
-
* 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
|
|
301
|
-
*/
|
|
302
|
-
trigger?: 'load' | 'leave';
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export interface HttpResOption {
|
|
306
|
-
/**
|
|
307
|
-
* 忽略指定path的资源
|
|
308
|
-
*/
|
|
309
|
-
ignorePaths?: string[];
|
|
310
|
-
/**
|
|
311
|
-
* 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
|
|
312
|
-
*/
|
|
313
|
-
trigger?: 'load' | 'leave';
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export interface SlowOption {
|
|
317
|
-
/**
|
|
318
|
-
* 加载时长大于该阈值,就认为是慢资源,默认1000,单位是ms
|
|
319
|
-
*/
|
|
320
|
-
threshold?: number;
|
|
321
|
-
/**
|
|
322
|
-
* 忽略指定path的资源
|
|
323
|
-
*/
|
|
324
|
-
ignorePaths?: string[];
|
|
325
|
-
/**
|
|
326
|
-
* 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
|
|
327
|
-
*/
|
|
328
|
-
trigger?: 'load' | 'leave';
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export interface ErrorHandlerData {
|
|
2
|
-
info: {
|
|
3
|
-
[propName: string]: any;
|
|
4
|
-
msg: string;
|
|
5
|
-
};
|
|
6
|
-
group: string;
|
|
7
|
-
dim?: {
|
|
8
|
-
[propName: string]: any;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ErrorConf {
|
|
13
|
-
// 抽样, 取值在[0, 1],为0,则相当于禁用,默认是0
|
|
14
|
-
sample: number;
|
|
15
|
-
// 自定义spy平台的分组
|
|
16
|
-
group: string;
|
|
17
|
-
// 异常数据上报前的自定义处理,可以修改data对象,增加信息和维度,如果返回false,则表示不上报该数据
|
|
18
|
-
handler?: (data: ErrorHandlerData) => boolean | void | undefined;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface WhiteScreenErrorConf extends ErrorConf {
|
|
22
|
-
// 超时时间,在到达超时时间后,执行检测,如果条件不成立,则认为会抛出白屏错误
|
|
23
|
-
timeout: number;
|
|
24
|
-
// css选择器
|
|
25
|
-
selector: string;
|
|
26
|
-
// css选择器
|
|
27
|
-
subSelector: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface SpyHeadConf {
|
|
31
|
-
// spy平台申请的pid
|
|
32
|
-
pid: string;
|
|
33
|
-
// 可选,用户log id
|
|
34
|
-
lid?: string;
|
|
35
|
-
// 可选,自定义日志服务器
|
|
36
|
-
logServer?: string;
|
|
37
|
-
jsError: ErrorConf;
|
|
38
|
-
resourceError: ErrorConf;
|
|
39
|
-
whiteScreenError: WhiteScreenErrorConf;
|
|
40
|
-
}
|