PageSpy

repository·main·Indexed 43 days ago

https://github.com/huolalatech/page-spy

A developer platform for remote web page debugging consisting of client-side SDKs and a web-based dashboard. It provides diagnostic data collection and visualization for various environments, including Web, HarmonyOS, Lynx, and miniprogram frameworks such as Alipay, UniAPP, and Taro.

Tokens
54K
Snippets
172
Records
240
Agent score
55%

What's inside PageSpy

  1. Overview of PageSpy SDKs

    main
    PageSpy is a developer platform designed for remote debugging of web pages. This repository contains the SDKs used to collect information from client environments. The collected data is sent to the [page-spy-web][page-spy-web] platform, which consumes, filters, organizes, and converts the information into a standardized format for visualization and debugging.
  2. Overview of Page Spy SDKs

    main

    Page Spy is a tool for remote debugging of web pages. This repository contains the SDKs used to collect page information. The collected data is then consumed by the page-spy-web project, which filters, organizes, and presents the data in a standardized format on a web interface.

    To use Page Spy, you typically need both the SDK (to collect data from your application) and the web dashboard (to view the collected data).

  3. What is DataHarborPlugin and how does it work?

    main

    The DataHarborPlugin provides offline caching and data downloading capabilities for PageSpy in browser environments.

    Historically, remote debugging required both the client and the debugging server to be online simultaneously. DataHarborPlugin breaks this requirement by listening for the public-data event to cache data locally on the client. When an issue is identified, users can export the cached data manually.

    Data Lifecycle:

    1. Data collection starts when new PageSpy() is called.
    2. Data is stored in client-side memory.
    3. When the accumulated data reaches the maximum threshold (defaulting to 10MB), the plugin generates an Object URL via URL.createObjectUrl() to temporarily store the data, and collection continues.
  4. What is DataHarborPlugin

    main

    The DataHarborPlugin is a PageSpy plugin designed for browser environments that enables offline data caching and downloading.

    Traditionally, remote debugging requires both the client and the debugging end to be online simultaneously. DataHarborPlugin breaks this requirement by listening to public-data events and storing data in the client's memory. When the accumulated data reaches a specific threshold (defaulting to 10MB), the plugin generates an Object URL via URL.createObjectUrl() to temporarily store the data, allowing users to export logs even after the session has ended or the connection is lost.

  5. Use MPEvalPlugin to run dynamic scripts in mini programs

    main

    The MPEvalPlugin is a plugin for the PageSpy mini program SDKs. It enables the execution of dynamic scripts within the mini program environment.

    This plugin is compatible with the following mini program SDKs:

    • @huolala-tech/page-spy-wechat
    • @huolala-tech/page-spy-alipay
    • @huolala-tech/page-spy-uniapp
    • @huolala-tech/page-spy-taro
    CAUTION

    You must remove this plugin from your code before submitting your mini program for official review, otherwise the review process will fail.

    import PageSpy from '@huolala-tech/page-spy-wechat';
    import MPEvalPlugin from '@huolala-tech/page-spy-plugin-mp-eval';
    
    // Register plugin
    PageSpy.registerPlugin(new MPEvalPlugin());
    // Init PageSpy
    const pageSpy = new PageSpy();
  6. Use PageSpy in offline mode

    main
    By setting offline: true in the InitConfig, the SDK enters "offline mode". In this mode, PageSpy will not attempt to create rooms or establish WebSocket connections with the debugger. This is useful for scenarios where you want to capture data without immediate real-time transmission (e.g., for later replay).
  7. Implement a custom PageSpyPlugin

    main

    To extend PageSpy, you can implement the PageSpyPlugin abstract class. A plugin is identified by its name property and can control its execution order using the enforce property.

    Plugin Lifecycle Methods

    • onInit(params: OnInitParams): Called when new PageSpy() is instantiated. Use this to set up data collection or listeners.
    • onMounted(params: OnMountedParams): Called after PageSpy has rendered (if applicable). Use this to inject UI elements into the PageSpy interface.
    • onReset(): Called when the user calls $pageSpy.abort(). Use this to clean up resources or UI elements added by the plugin.

    Execution Order

    Plugins are executed based on the enforce property:

    1. enforce: "pre" (runs first)
    2. No enforce property (runs second)
    3. enforce: "post" (runs last)
    import { PageSpyPlugin, OnInitParams, OnMountedParams } from '@huolala-tech/page-spy-types';
    
    export default class MyPlugin implements PageSpyPlugin {
      name = 'MyPlugin';
      enforce?: 'pre' | 'post'; // Optional execution order
    
      onInit(params: OnInitParams) {
        // Setup logic
      }
    
      onMounted(params: OnMountedParams) {
        // UI injection logic
      }
    
      onReset() {
        // Cleanup logic
      }
    }
  8. Understand RRWebPlugin data dispatching and playback

    main
    Because rrweb data can become very large due to complex DOM structures or high user interaction, this plugin is optimized to reduce network overhead. Instead of streaming all raw data, it dispatches 'public-data' events. This allows statistical plugins (like DataHarborPlugin) to collect the data efficiently without burdening the network during real-time debugging.
  9. How RRWeb data is dispatched

    main

    Because rrweb-event data can be significantly large due to complex webpage structures and high interaction frequency, this plugin is optimized to reduce network overhead.

    Instead of real-time transmission of every mutation, the plugin only dispatches the public-data event for statistical plugins to collect. This prevents real-time transmission from imposing a heavy burden on the network during debugging.

  10. Communicate with the debugger via socketStore

    main

    Plugins interact with the PageSpy debugger/API using the socketStore provided in onInit and onMounted.

    Broadcasting Data

    To send data from the client to the debugger, use socketStore.broadcastMessage(message).

    Behavioral Convention: If a plugin collects platform behavior data that it wants to make available for statistics or persistence, it should also dispatch a "public-data" internal event using socketStore.dispatchEvent('public-data', message). This allows other plugins to intercept and collect this data.

    Handling Debugger Messages

    To listen for specific messages sent from the debugger, use socketStore.addListener(eventName, callback). The callback provides a reply function which, when called, sends a unicast response back to the specific debugger instance that initiated the request.

    Message Format

    A typical message item follows the SpyMessage.MessageItem shape:

    • type: The message type (e.g., 'rrweb-event').
    • role: The sender role (e.g., 'client').
    • data: The actual payload.
  11. Built-in PageSpy Plugins

    main

    The Lynx SDK includes several built-in plugins that automatically detect runtime availability:

    • ConsolePlugin: Proxies console.log, info, error, warn, and debug.
    • SystemPlugin: Reports PageSpy client information and available Lynx system information.
    • NetworkPlugin: Prioritizes proxying fetch; proxies XMLHttpRequest only if exposed by the runtime.
    • WebSocketPlugin: Proxies WebSocket traffic only if globalThis.WebSocket is constructible.
    • ErrorPlugin: Listens for global errors or unhandled rejections if the runtime exposes the necessary hooks.

    You can disable any of these by adding their name to the disabledPlugins array in the configuration.

  12. How to communicate via socketStore in plugins

    main

    Plugins interact with the debugging terminal and other plugins using the socketStore instance provided in lifecycle methods.

    Broadcasting Data

    To send data to the debugging terminal, use socketStore.broadcastMessage(message).

    Convention: If a plugin collects platform behavior data that other plugins might need (e.g., for statistics), it is recommended to also dispatch a public-data internal event using socketStore.dispatchEvent('public-data', message). This allows other plugins to uniformly collect data from this event.

    Listening for Terminal Events

    You can listen for specific messages sent from the debugging terminal using socketStore.addListener(eventName, callback). The callback provides a source (containing the data) and a reply function. Calling reply(result) will unicast the result back to the specific debugging terminal that sent the request.

    // Broadcasting data
    socketStore.broadcastMessage({ type: 'my-event', role: 'client', data: {} });
    socketStore.dispatchEvent('public-data', { type: 'my-event', role: 'client', data: {} });
    
    // Listening and replying
    socketStore.addListener('request-data', ({ source }, reply) => {
      const params = source.data;
      const result = { status: 'ok' };
      reply(result); // Sends result back to the terminal
    });