npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

spy-client

v2.1.10

Published

spy client

Downloads

2,401

Readme

spy-client Build Status

介绍

日志采集模块,提供一系列方便的api供使用

  1. 新版2.x部分API不再兼容1.x
  2. 从2.1.0版本开始,不再兼容IE8及以下IE浏览器
  3. 从2.1.8版本开始,兼容小程序环境(new Image类发送);通过继承类,覆盖request方法,可以支持Node.js/跨端框架/小程序环境

安装

npm install spy-client --save

CDN方式

不是一次性3个JS都引入,具体往下看

<!--增强版SDK-->
<script src="https://code.bdstatic.com/npm/[email protected]/dist/spy-client.min.js" type="text/javascript"></script>

<!--增强版SDK spy-head-->
<script src="https://code.bdstatic.com/npm/[email protected]/dist/spy-head.min.js" type="text/javascript"></script>

<!--基础版SDK-->
<script src="https://code.bdstatic.com/npm/[email protected]/dist/spy-client-basic.min.js" type="text/javascript"></script>

如果对于一些指标想理解更准确,看源码是最佳方式 SDK源码

SDK的指标采集请酌情选用,不要一股脑全用上,如果只用了一项采集功能,但SDK体积太大,可以考虑自行编译,看文档最后

快速使用

初始化

const SpyClient = require('spy-client');
const spy = new SpyClient({
    pid: '1_1000', // 必须
    lid: '', // 可选,页面的logid
    sample: 1 // 可选,默认为1, 全局抽样,取值:[0-1], 所有发送接口都受到该抽样,单个发送接口的sample配置会覆盖该抽样。
});

发送性能日志

// 发送性能日志
spy.sendPerf({
    // 可选, 分组,默认common,用户自定义
    group: 'test',
    // 必须, 指标信息,每个字段为一个指标,由用户自定义,这里的fisrtScreen、whiteScreen等都是业务自己定义,后续会在平台上配置好,平台会从该字段取对应指标信息。
    // 这些指标需要你自行计算好时间再发送,不能带单位
    info: {
        tcp: 1200,
        domReady: 600
    },
    // 可选,维度信息,每个字段为一个维度,由用户自定义,这里的netType、pageType都是业务自己定义,后续会在平台上配置好,平台会从该字段取对应维度信息。
    dim: {
        os: 'ios',
        netType: 'wifi'
    }
});

SDK说明

SDK分两种

  • 基础版SDK:提供最基础和最简单的功能,如果这些功能能满足你,那么直接使用该SDK即可,因为体积较小
  • 增强版SDK:除了基础版SDK功能外,集合了丰富的常用的性能和异常指标统计

接下来分别介绍

基础版SDK

提供最基础和最简单的功能,如果这些功能能满足你,那么直接使用该SDK即可

// basic spy-client 基本用法,最简单功能
const SpyClient = require('spy-client/dist/spy-client-basic');
const spy = new SpyClient({
    pid: '1_1000', // 必须
    lid: '', // 可选,页面的logid
    sample: 1 // 可选,默认为1, 全局抽样,取值:[0-1], 所有发送接口都受到该抽样,单个发送接口的sample配置会覆盖该抽样。
});

以下先简单列举所有可用API示例


// 发生性能日志,本质是数值型的metric数据
spy.sendPerf({
    // 可选, 分组,默认common,用户自定义
    group: 'test',
    // 必须, 指标信息,每个字段为一个指标,由用户自定义,这里的fisrtScreen、whiteScreen等都是业务自己定义,后续会在平台上配置好,平台会从该字段取对应指标信息。
    // 这些指标需要你自行计算好时间再发送,不能带单位
    info: {
        tcp: 1200,
        domReady: 600
    },
    // 可选,维度信息,每个字段为一个维度,由用户自定义,这里的netType、pageType都是业务自己定义,后续会在平台上配置好,平台会从该字段取对应维度信息。
    dim: {
        os: 'ios',
        netType: 'wifi'
    }
});


// 发送异常日志
spy.sendExcept({
    // 必须, 异常信息,msg字段是必须的,是异常唯一标识。其他字段作为补充信息,由用户自定义
    info: {
        msg: 'abc is not undefined', // msg字段是必须的,必须的,必须的,会统计相同msg的总量
        stack: 'xxxxx',
        file: 'xxxxxxx'
    },
    // 可选, 分组,默认common,用户自定义
    group: 'test',
    // 可选,维度信息,每个字段为一个维度,由用户自定义
    dim: {
        os: 'ios'
    }
});

// 发送分布日志
spy.sendDist({
    info: {
        from: 'hao123'
    },
    dim: {
        os: 'ios'
    }
});

// 发送计数日志
spy.sendCount({
    info: {
        from: 'hao123'
    },
    dim: {
        os: 'ios'
    }
});

// 如果能拿到error实例,通过该方法快速上报异常,默认会获取stack等信息
spy.sendExceptForError(new Error('error'), {
    dim: {
        os: 'ios'
    }
});

// 最基础的API,需要自行指定type字段
spy.send({
    type: 'perf'
    info: {
        domReady: 1000
    },
    dim: {}
});


// 统计辅助方法
spy.startMark('playTime');
let time = spy.endMark('playTime');
console.log(time); // output: 1000

spy.startMark('pauseTime');
spy.endMark('pauseTime'); // 假设中间执行花费1s
console.log(spy.getAllMark());
// output
// {
//     playTime: 1000,
//     pauseTime: 1000
// }

spy.clearMark('pauseTime'); // 清除pauseTime
spy.clearAllMark(); // 清除所有mark的信息

基础版可支持小程序/Node.js/跨端框架环境

1 . 小程序 不用做任何修改,就支持采用new Image发送日志。

2 . Node.js/跨端框架环境

Node.js,跨端框架,以及小程序环境中若采用spy.send(xxx, true)方式,则需要继承SpyClient类,覆盖request方法. 如果是Node.js,需要服务器有外网权限

const SpyClient = require('spy-client/dist/spy-client-basic');
// 若环境编译不支持umd,则可以导入es module
// const SpyClient = require('spy-client/dist/spy-client-basic.esm');

class SpyClientNode from SpyClient {
    request(url: string, data?: any) {
        axios({
            method: data ? 'post' : 'get',
            url,
            data: data ? JSON.stringify(data) : data,
        });
    }
}

const spy = new SpyClientNode({
    pid: '1_1000', // 必须
    lid: '', // 可选,页面的logid
    sample: 1 // 可选,默认为1, 全局抽样,取值:[0-1], 所有发送接口都受到该抽样,单个发送接口的sample配置会覆盖该抽样。
});
spy.sendPerf({
    info: {
        responseTime: 200
    }
});

增强版SDK

增强版SDK分成了2部分

  1. spy-head:有些功能我们希望越早生效越好,比如全局JS报错监控。因此把这些功能最小集抽成一个单独JS,以便可以插入head标签内,也不会全量引入整个SDK在头部。当然,放到任何地方都是可以,开发者自行决策即可。此部分包含的功能有

    • 异常:全局JS报错监控、资源加载失败监控、白屏异常监控
    • 性能:Longtask等信息采集,真正的统计是在spy-client里,只是越早采集,能获取更多的longtask
  2. spy-client:此部分提供了丰富的性能和异常的指标统计,其中部分功能依赖于spy-head,包含的功能有

    • 性能指标采集:包含体积、卡顿、速度等60+个性能指标采集方法
    • 异常:包含大于150K的大图片采集、HTTPS环境下HTTP资源采集
    • 辅助方式: mark系列辅助方法

增强版SDK仅支持浏览器环境

spy-head使用

spy-head JS可以视情况通过script内联或嵌入其他JS里

如果要启用一项异常监控功能,需要设置其抽样sample不为0

<script>
// spy-head js可以视情况通过script内联或外链,外链地址可见文档开头的CDN
const spyHead = require('spy-client/dist/spy-head');
spyHead.init({
    pid: '1_1', // spy申请的pid
    lid: '', // 业务的log id,可选

    // 数据类型:异常,触发时间:监听的window.addEventListen('error')有资源加载失败时
    // 上报信息里包含资源的标签名,资源地址,xpath
    // 用不着的话,需要删掉这个配置
    resourceError: {
        // 发送的分组名称,可以自定义
        group: 'resource',
        // 抽样,禁用可以设置为0
        sample: 1,
        // 对发送之前的数据进行操作,如果不想发送,返回false即可
        // 如果想增加维度,可以自定加上data.dim字段
        // 用不着的话,可以删掉这个函数
        handler: function (data) {

        }
    },
    // 数据类型:异常,触发时间:监听的全局报错window.addEventListen('error'),有未被捕获的全局异常抛出时
    // 上报信息里包含错误message,stack,之前已发生的所有错误等
    // 用不着的话,需要删掉这个配置
    jsError: {
        // 发送的分组名称,可以自定义
        group: 'js',
        // 抽样,禁用可以设置为0
        sample: 1,
        // 对发送之前的数据进行操作,如果不想发送,返回false即可
        // 如果想增加维度,可以自定加上data.dim字段
        // 用不着的话,可以删掉这个函数
        handler: function (data) {

        }
    },
    // 数据类型:异常,触发时间:OnJudgeReturnFalseWhenTimeout
    // 上报信息里包含之前已发生的所有错误、dns、tcp、请求响应时间(可能为负,说明该过程没有完成)、设备信息等
    // 用不着的话,需要删掉这个配置
    whiteScreenError: {
        // 抽样,禁用可以设置为0
        sample: 1,
        // 发送的分组名称,可以自定义
        group: 'whiteScreen',
        // 一旦以下逻辑不满足,就认为白屏:document.querySelector(selector)的元素包含 document.querySelector(selector).querySelector(subSelector) 并且 document.querySelector(selector) 的高度大于屏幕高度的2/3
        selector: 'body',
        subSelector: 'button1',
        // 单位ms,在timeout后,执行上述检测
        timeout: 6000,
        // 对发送之前的数据进行操作,如果不想发送,返回false即可
        // 如果想增加维度,可以自定加上data.dim字段
        // 用不着的话,可以删掉这个函数
        handler: function(data) {

        }
    }
});
<script>

像Vue等组件框架会对组件代码做try catch,然后打印到console,这种错误情况是不会有全局错误的,即window.onerror不会触发。只能使用框架的全局error回调(比如Vue.config.errorHandler)去拿到错误信息,再调用spy.sendExcept上报。 所以在发现上述jsError全局异常监听失效时,请先自行调试是否能通过window.addEventListen('error')监听到

主体SDK spy-client

// enhanced spy-client
const SpyClient = require('spy-client');
const spy = new SpyClient({
    pid: '1_1000', // 必须
    lid: '', // 可选,页面的logid
    sample: 1 // 可选,默认为1, 全局抽样,取值:[0-1], 所有发送接口都受到该抽样,单个发送接口的sample配置会覆盖该抽样。
});

基于performance timing的基本指标

// 类型:性能,触发时间:500MsAfterOnLoad,说明:performance timing的数据采集基本指标
spy.listenTiming(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface TimingMetric {
    // dns解析
    dns: number;
    // tcp链接
    tcp: number;
    // 主文档请求
    request: number;
    // 主文档响应时间
    response: number;
    // DOM解析时间:Dom解析开始到结束时间
    // 这是从页面部分数据返回,浏览器开始解析doc元素到最底部的script脚本解析执行完成
    // 脚本里触发的异步方法或绑定了更靠后的事件,不再纳入范围内
    parseHtml: number;
    // DOM解析完成总时间:页面开始加载到Dom解析结束
    // 很多事件绑定是在domContentLoaded事件里的,所以等其结束,一般页面元素的事件绑定好了,用户可以正确交互
    // 当然存在在该加载事件之后绑定元素事件情况,但不再此考虑范围内
    domReady: number;
    // 处理所有注册的load事件函数的时间
    loadEventHandle: number;
    // onload完成时间
    // 基本该做的都做完,资源也都加载完成了
    // 当然在onload事件处理函数里启动了异步方法,不再纳入范围内
    load: number;
    // first-paint https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
    fp?: number;
    // first-contentful-paint  https://w3c.github.io/paint-timing/#sec-PerformancePaintTiming
    fcp?: number;
    // T7内核计算的首次绘制, 单位ms
    t7FirstPaint?: number;
    // T7内核计算的首屏时间, 单位ms
    t7FirstScreen?: number;
}

Largest Contentful Paint

最大块内容绘制完成时间

  • 依赖:spy-head.js
// 类型:性能,触发时间:500MsAfterOnLoad
spy.listenLCP(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface LCPMetric {
    // Largest Contentful Paint https://web.dev/lcp/
    // 在onload时间内最大块内容绘制完成时间
    lcp: number;
}

FID

首次输入延迟,衡量首次交互卡顿

  • 依赖:spy-head.js
// 类型:性能,触发时间:OnInput
spy.listenFID(function (metric) {
    spy.sendPerf({
        group: 'fid',
        info: metric
    });
});

metric定义

export interface FIDMetric {
    // First Input Delay https://web.dev/fid/
    // 首次输入延迟
    fid: number;
}

TTI

用户可完全交互时间

// 数据类型:性能,触发时间:当第一次出现5s内没有网络请求(默认排查了gif请求),且没有longtask产出时
spy.listenTTI(function (metric) {
    spy.sendPerf({
        group: 'tti',
        info: metric
    });
});

metric定义

export interface TTIMetric {
    // Time to Interactive https://web.dev/tti/
    // 用户可完全交互时间
    tti: number;
}

获取资源信息

获取资源的本身大小、传输大小、数量、传输、缓存率

// 数据类型:性能,触发时间:500MsAfterOnLoad
spy.listenResource(function (metric, hostMetric) {
    spy.sendPerf({
        info: metric
    });

    // 分域名进行统计的
    console.log('hostMetric', hostMetric);
});

metric定义

export interface ResourceMetric {
    // 页面整体大小:包括主文档、所有JS、CSS、Img、Font,单位KB
    allSize: number;
    // 主文档大小 KB
    docSize: number;
    // 主文档的响应header的大小,包含cookie等 KB
    headerSize: number;

    // js外链的个数
    jsNum: number;
    cssNum: number;
    imgNum: number;
    fontNum: number;

    // 所有JS外链的大小
    jsSize: number;
    cssSize: number;
    imgSize: number;
    fontSize: number;

    // 页面整体网络传输大小,通常来说资源有了缓存,传输大小就为0,另外有Gzip的话,传输大小相比资源本身大小也要小很多
    allTransferSize: number;
    // 主文档网络传输大小
    docTransferSize: number;
    // 所有JS外链的传输大小
    jsTransferSize: number;
    cssTransferSize: number;
    imgTransferSize: number;
    fontTransferSize: number;

    // js cache率
    jsCacheRate: number;
    cssCacheRate: number;
    imgCacheRate: number;
};

hostMetric定义

export interface ResourceHostMetric {
    [host: string]: {
        hostNum: number;
        hostSize: number;
        hostTransferSize: number;
        hostDuration: number;
        hostCacheRate: number;
    };
};

加载慢的资源

// 数据类型:异常,触发时间:500MsAfterOnLoad
spy.listenSlowResource(function (info) {
    spy.sendExcept({
        info: info
    });
}, {threshold: 1000});

info定义

export interface ResourceErrorInfo {
    // 发生异常的资源链接
    msg: string;
    // 发生异常的资源元素的xpath信息,一直到body
    xpath: string;
    // 资源host
    host: string;
    // 资源类型
    type: string;
    // 资源耗时
    dur?: number;
}

第二个参数,option定义

export interface SlowOption {
    /**
     * 加载时长大于该阈值,就认为是慢资源,默认1000,单位是ms
     */
    threshold?: number;
    /**
     * 忽略指定path的资源
     */
    ignorePaths?: string[];
    /**
     * 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
     */
    trigger?: 'load' | 'leave';
}

大于150KB的大图检测

大于150KB(默认,第二个参数可以修改)的来自img标签的大图检测。

// 数据类型:异常,触发时间:500MsAfterOnLoad
spy.listenBigImg(function (info) {
    spy.sendExcept({
        info: info
    });
});

info定义

export interface ResourceErrorInfo {
    // 发生异常的资源链接
    msg: string;
    // 发生异常的资源元素的xpath信息,一直到body
    xpath: string;
    // 资源host
    host: string;
    // 资源类型
    type: string;
    // 资源耗时
    dur?: number;
}

第二个参数,option定义

export interface BigImgOption {
    /**
     * 体积大于该阈值,就认为是大图,默认150,单位是kb
     */
    maxSize?: number;
    /**
     * 忽略指定path的资源
     */
    ignorePaths?: string[];
    /**
     * 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
     */
    trigger?: 'load' | 'leave';
}

HTTPS页面里的HTTP资源检测

// 数据类型:异常,触发时间:500MsAfterOnLoad
spy.listenHttpResource(function (info) {
    spy.sendExcept({
        info: info
    });
});

info定义

export interface ResourceErrorInfo {
    // 发生异常的资源链接
    msg: string;
    // 发生异常的资源元素的xpath信息,一直到body
    xpath: string;
    // 资源host
    host: string;
    // 资源类型
    type: string;
    // 资源耗时
    dur?: number;
}

第二个参数,option定义

export interface HttpResOption {
    /**
     * 忽略指定path的资源
     */
    ignorePaths?: string[];
    /**
     * 触发时机,在load事件触发后,还是在用户离开页面后,收集出现的加载慢的资源。,默认是load
     */
    trigger?: 'load' | 'leave';
}

T7内核首屏时间内的LongTask信息

  • 依赖:spy-head.js
// 数据类型:性能,触发时间:OnLoad
spy.listenFSPLongTask(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface FSPLongtaskMetric {
    // 在T7内核首屏时间内, 每个longtask的时间总和
    fspLongtaskTime: number;
    // 在T7内核首屏时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
    // Total Blocking Time定义:
    fspTBT: number;
    // T7内核首屏时间
    fspTotalTime: number;
    // 在T7内核首屏时间内, Longtask率 = 100 * fspLongtaskTime / fspTotalTime
    fspLongtaskRate: number;
    // 在T7内核首屏时间内的Longtask数量
    fspLongtaskNum: number;
}

Largest Contentful Paint时间内LongTask信息

  • 依赖:spy-head.js
// 数据类型:性能,触发时间:500MsAfterOnLoad
spy.listenLCPLongTask(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface LCPLongtaskMetric {
    // 在Largest Contentful Paint时间内, 每个longtask的时间总和
    lcpLongtaskTime: number;
    // 在Largest Contentful Paint时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
    lcpTBT: number;
    // Largest Contentful Paint时间
    lcpTotalTime: number;
    // 在Largest Contentful Paint时间内, Longtask率 = 100 * lcpLongtaskTime / lcpTotalTime
    lcpLongtaskRate: number;
    // 在Largest Contentful Paint时间内的Longtask数量
    lcpLongtaskNum: number;
}

页面加载过程的LongTask信息

  • 依赖:spy-head.js
// 数据类型:性能,触发时间:OnLoad
spy.listenLoadLongTask(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface LoadLongtaskMetric {
    // 在onload即页面加载完成时间内, 每个longtask的时间总和
    loadLongtaskTime: number;
    // 在onload即页面加载完成时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
    loadTBT: number;
    // onload即页面加载完成时间
    loadTotalTime: number;
    // 在onload即页面加载完成时间内, Longtask率 = 100 * loadLongtaskTime / loadTotalTime
    loadLongtaskRate: number;
    // 在onload即页面加载完成时间内的Longtask数量
    loadLongtaskNum: number;
}

页面完整周期内的LongTask信息

开始加载页面到第一次离开页面(隐藏或点出)时间内的LongTask信息

  • 依赖:spy-head.js
// 数据类型:性能,触发时间:OnLeavingPageFirstly
spy.listenPageLongTask(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface PageLongtaskMetric {
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内, 每个longtask的时间总和
    pageLongtaskTime: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内,Total Blocking Time时间总和,即Sum(每个longtask的时间 - 50)
    pageTBT: number;
    // 开始加载页面到第一次离开页面(隐藏或点出)时间
    pageTotalTime: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内, Longtask率 = 100 * pageLongtaskTime / pageTotalTime
    pageLongtaskRate: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内的Longtask数量
    pageLongtaskNum: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的longtask的时间总和
    pageIframeLongtaskTime: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的Longtask率 = 100 * pageIframeLongtaskTime / pageTotalTime
    pageIframeLongtaskRate: number;
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内,每个来自iframe内的Longtask数量
    pageIframeLongtaskNum: number;
}

Cumulative Layout Shift

页面布局的变化程度, 变化过多,可能让用户觉得页面不稳定,抖动

  • 依赖:spy-head.js
// 数据类型:性能,触发时间:OnLeavingPageFirstly
spy.listenLayoutShift(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface LayoutShiftMetric {
    // Cumulative Layout Shift定义 https://web.dev/cls/
    // 在开始加载页面到第一次离开页面(隐藏或点出)时间内的 Cumulative Layout Shift
    layoutShift: number;
}

内存信息

页面使用内存信息

在页面第一次离开时(隐藏或点出)触发

// 数据类型:性能,触发时间:在页面第一次离开时(隐藏或点出)
spy.listenMemory(function (metric) {
    spy.sendPerf({
        info: metric
    });
});

metric定义

export interface MemoryMetric {
    // 已使用内存, 单位KB
    usedJSHeapSize: number;
    // 分配给页面的内存,单位KB
    totalJSHeapSize: number;
    // 内存限制,单位KB
    jsHeapSizeLimit: number;
    // 内存使用率百分比 = 100 * usedJSHeapSize / totalJSHeapSize
    usedJSHeapRate: number;
}

Navigator信息

获取一些设备信息

// 数据类型:性能,触发时间:OnLoad
const info = spy.getNavigatorInfo();

info定义

export interface NavigatorInfoMetric {
    // 网络下载速度 https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/connection
    downlink?: number;
    // 网络类型
    effectiveType?: '2g' | '3g' | '4g' | 'slow-2g';
    // 估算的往返时间
    rtt?: number;
    // 数据保护模式
    saveData?: boolean;
    // 设备内存 https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory
    deviceMemory?: number;
    // 设备逻辑核数  https://developer.mozilla.org/en-US/docs/Web/API/NavigatorConcurrentHardware/hardwareConcurrency
    hardwareConcurrency?: number;
}

Example

样例参考 Example

自定义构建

clone准备

如果觉得spy-client太大,只想要部分模块,比如禁用 longtask,可以拉取源码,自行编译

git clone https://github.com/kaivean/spy-client.git

cd spy-log
npm install

禁用模块

比如禁用longtask,前往src/spy-client.ts

在顶部注释掉import

// import Longtask from './module/longtask';

在constructor里注释掉register

// this.register(new Longtask());

构建

npm run build

然后找到dist/spy-client.min.js 就是构建压缩版代码

开发

# 启动本地调试页面,进行调试
npm run example

# 进行watch 编译, 一般和上个命令配合使用
npm run watch

# lint
npm run lint

# 测试
npm run test

# production编译,产出到dist
npm run build

# development编译,产出到dist
npm run dev

# 发布
# 1. 构建测试
npm run release_pre
# 2. 提交代码
git add . && git commit -m "升级/Fix"
# 3. 发布npm包,增加tag
npm run release

# 4. 修改Readme文档里版本号
git add . && git commit -m "修改文档版本"
# 5. 把代码push到远程
npm run release_post