Skip to content
Blucas edited this page Jul 12, 2024 · 26 revisions

⚠️ Document has been migrated

Caution

All docs are migrated to the official site https://pagespy.org from 2024.7.10.

How can I quickly understand what PageSpy is and how to use it?

PageSpy has prepared introductory videos for everyone. The videos cover the background of using PageSpy, how to use it, various deployment scenarios, and more. Please visit Youtube Youtube to watch and learn.

What about the compatibility?

How to hide the logo rendered by SDK in client?

window $pageSpy = new PageSpy({
  // ... other config
  autoRender: false
})

What parameters can be passed during the instantiation of PageSpy, and what are their respective purposes?

Tip

PageSpy instantiation can include the following optional parameters, each serving a specific purpose with its default values explained.

window.$pageSpy = new PageSpy({
    // The SDK automatically analyzes the path from which it is imported
    // to determine the server address (api) and client's origin (clientOrigin).
    // If you load SDK by <script src="https://example.com/page-spy/index.min.js">, the SDK will internally set:
    //   - api: "example.com"
    //   - clientOrigin: "https://example.com"
    // Manually specify if your service is deployed elsewhere.
    api: "",
    clientOrigin: "", // only for browser sdk
    
    // Project serves as an aggregation of information and can be searched in the debug client's room list.
    project: "default",
    
    // Title allows users to provide custom parameters, useful for distinguishing the current debugging client.
    // The corresponding information is displayed below the "Device ID" on each debug connection panel.
    title: "--",
    
    // Indicates whether the SDK, upon initialization, automatically renders the "circular white logo on a white background" control
    // in the bottom left corner of the client. If set to false, you can manually render it using window.$pageSpy.render().
    autoRender: true, // only for browser sdk
    
    // Manually specify the scheme of the PageSpy service.
    // Useful when the SDK cannot correctly analyze the scheme; for example, when using PageSpy's browser extension,
    // it may be imported as chrome-extension://xxx/sdk/index.min.js, which the SDK might interpret as invalid "chrome-extension://"
    // and fallback to ["http://", "ws://"].
    //   - (Default) Pass undefined or null: SDK will automatically analyze;
    //   - Pass a boolean value:
    //     - true: SDK will access PageSpy service through ["https://", "wss://"]
    //     - false: SDK will access PageSpy service through ["http://", "ws://"]
    enableSSL: null,


    // After adding support for offline replay in [email protected], 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, // only for browser sdk

    // Customize the logo source
    logo: '', // only for browser sdk

    // Customize the logo style
    logoStyle: {}, // only for browser sdk
})

How to integrate PageSpy into frameworks?

PageSpy has published integration guides for all popular frameworks on the CodeSandbox platform. You can experience it online by visiting:

Is test.jikejishu.com an officially provided domain? Can it be used continuously?

https://test.jikejishu.com/ is a temporary service we set up to allow users to experience and learn PageSpy online. We do not guarantee 24-hour availability, data security, and any losses incurred are at your own risk. We strongly recommend deploying PageSpy in private servers or intranets after the initial experience.

Why can I access port 6752 locally, but not after deploying it to the server?

Check if the firewall on the server or the security group rules have opened port 6752.

How should I configure Nginx to directly access through a domain?

Here is the Nginx configuration for https://test.jikejishu.com/ as a reference:

server {
    listen 443 ssl;
    server_name test.jikejishu.com;

    if ($scheme != https) {
        rewrite ^(.*)$  https://$host$1 permanent;
    }
    
    ssl_certificate /etc/letsencrypt/live/test.jikejishu.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.jikejishu.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:6752;
        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection "upgrade";
    }
}

server {
    if ($host = test.jikejishu.com) {
        return 301 https://$host$request_uri;
    }

    listen 80;
    listen [::]:80;
    server_name test.jikejishu.com;
    return 404;
}

How can the debugging side add some security authentication protection, allowing access only for authenticated developers?

You can implement security protection on the server by setting up an IP whitelist or using HTTP Authorization.

  • Example Nginx configuration for IP whitelist:

    server {
        location / {
            # Allow only specified IP addresses to access
            allow <ip>;
    
            # Deny all other clients except those in the allow list
            deny all;
        }
    }
  • Nginx configuration for HTTP Authorization, requiring a username and password for access:

    1. Generate a username and password file using htpasswd:
    # Enter the password when prompted and confirm it
    htpasswd -c /etc/nginx/.htpasswd <username>
    1. Configure the auth_basic module in the Nginx file:
    server {
        location / {
            auth_basic "Please enter your username and password to access the PageSpy service";
            auth_basic_user_file /etc/nginx/.htpasswd;
        }
    }
    

I don't want to manually integrate into my project. Is there a way to avoid modifying the business project code?

PageSpy has prepared a browser extension for you. The extension offers the following features:

  • Automatically injects the latest version of the SDK.
  • Automatically completes the instantiation process.
  • Provides configuration rules for injected domains.

Click here to use: HuolalaTech/page-spy-extension

Can I use a Tampermonkey script?

You can use the following script as a reference:

// ==UserScript==
// @name         Inject PageSpy Script
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Inject script on xxx.yyy
// @author       You
// @match        <matching rules, e.g., example.com>
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    var script1 = document.createElement('script');
    script1.setAttribute('crossorigin', 'anonymous');
    // Replace the actual SDK URL in a real project
    script1.src = 'https://test.jikejishu.com/page-spy/index.min.js';

    var script2 = document.createElement('script');
    script2.textContent = 'window.$pageSpy = new PageSpy();';

    document.head.prepend(script1);
    script1.onload = () => {
        document.head.appendChild(script2);
    }
})();

The business project is deployed on HTTPS, and PageSpy is deployed on HTTP. What should I do if there are console errors?

Browsers prevent loading HTTP resources from an HTTPS site because HTTPS provides encryption and security during data transmission, while HTTP is plaintext and poses a security risk.

It is recommended to upgrade PageSpy to use HTTPS directly to resolve this issue effectively.

How to debug a specific user individually?

The simplest solution is to have the user use the PageSpy browser extension, which is suitable for highly cooperative users and PC projects. However, this premise is quite demanding.

For an H5 project in production that needs to use PageSpy, what should be done? Enabling it for all users is obviously not practical.

Consider the two-step process of PageSpy's effectiveness:

  • Introducing the SDK through the <script> tag in the head;
  • Instantiation;

Before the second step of instantiation, the introduced <script> does not have any effect on the project. To debug a specific user, the key lies in the second step: where to instantiate PageSpy on the user's terminal. There are two possible solutions:

  • Dynamically respond to HTML: If user identification can be obtained when requesting HTML and HTML can be dynamically injected, it's possible to decide whether to inject the <script> and instantiation logic before returning HTML to the user;

  • Let users enable it with a gesture (in planning): By default, inject the SDK but don't instantiate it. Allow users to trigger special gestures to enable debugging;

Friendly reminder: In addition to technical implementation, attention should be paid to legal and security risks.

Can I interact directly with the client of the Page panel?

No, direct interaction is not allowed. If you need to perform certain interactions, you can try entering code at the bottom of the Console panel for execution, and then back to the Page panel to see the interface feedback.

How can I inspect CSS styles in the Page panel?

The Page panel renders document.documentElement.outerHTML from the client into an iframe element. You can inspect elements directly through the local Devtool.

The style of the Page panel is not correct?

Due to the differences in rendering environments between the client and the debugging side (e.g., the client's browser version being Chrome 75 and the debugging side's browser version being Chrome 120), the styles are provided for reference only.

Can't the Page panel fully restore the content of the client?

The SDK can capture a "screenshot" of the page and send it to the debugging side. However, this approach has its limitations:

  • "Images" have a larger data volume compared to text, leading to increased network transmission overhead;
  • It adds to the size and complexity of the SDK;
  • If there is a "style error", QA can provide precise feedback to developers on remote collaboration;

For these reasons, the styles in the Page panel are provided for reference only.

How to deploy on sub-path?

We have added support for allowing users to deploy the service for accessing by sub-path in 1.5.4 version. The installation process remains unchanged; the only adjustment required is in the nginx configuration:

server {
    # ...

    location /<sub-path>/  {
        # the <sub-path> is same as above
        rewrite ^/<sub-path>/(.*)$ /$1 break;
        proxy_pass            http://127.0.0.1:6752;
        proxy_http_version    1.1;
        proxy_set_header      Upgrade $http_upgrade;
        proxy_set_header      Connection "upgrade";
        proxy_set_header      Host $host;
        proxy_set_header      X-Real-IP $remote_addr;
        proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # the <sub-path> is same as above
    location /<sub-path> {
        return 301 $scheme://$host$request_uri/;
    }
}

After adjusting the configuration, simply restart Nginx to enable access via subpaths. And it's important to note that you need to pass api to tell SDK the sub-path, for example:

window.$pageSpy = new Page({
    api: '<host>/<sub-path>'
})

How to modify API service configuration?

When you deploy the service through the NPM package deployment method and execute page-spy-api in the terminal, a configuration file named config.json will be generated in the runtime directory. This file allows you to configure the service port and support multiple-instance deployment.

  • Modify the config.json:

    {
      "port": "6752",
      "maxLogFileSizeOfMB": "10240",
      "maxLogLifeTimeOfHour": "720",
      "corsConfig": {
          "allowOrigins": string[],
          "allowHeaders": string[],
          "allowMethods": string[],
          "exposeHeaders": string[]
      }
    }
  • Multi-instance deployment (Requires upgrading to version 1.5.0 or above)

    The rpcAddress configuration is used for multi-instance deployment, where ip and port represent the IP addresses and RPC ports of multiple machines. Multiple instances communicate with each other through RPC, and the program starts the RPC service based on the machine's IP. Therefore, it is important to ensure that IP addresses are unique to avoid potential issues of message confusion or loss.

    {
      "port": "6752",
      "rpcAddress": [
        {
          "ip": "192.168.123.1",
          "port": "20008"
        },
        {
          "ip": "192.168.123.2",
          "port": "20008"
        }
      ]
    }

Why is there some errors when starting page-spy-api globally installed with pnpm using pm2?

Packages installed globally with pnpm are wrapped in a shell script by pnpm. In other words, when executing pm2 start page-spy-api, it actually finds a shell script. pm2 is unable to interpret and execute this shell script, resulting in an error.

To resolve this issue, you can install the package using yarn or npm, there have a discussion: https://github.com/Unitech/pm2/issues/5416

How to upgrade the latest version after a new release?

  • If you deploy using docker:
# Update the image
docker pull ghcr.io/huolalatech/page-spy-web:latest

# Stop the running PageSpy container
docker stop pageSpy && docker rm -f pageSpy

# Restart the container
docker run -d --restart=always -p 6752:6752 --name="pageSpy" ghcr.io/huolalatech/page-spy-web:latest
  • If you deploy using NPM package:
# Update the package (yarn)
yarn global upgrade @huolala-tech/page-spy-api@latest

# Update the package (npm)
npm install -g @huolala-tech/page-spy-api@latest

# Restart using pm2
pm2 restart page-spy-api

Under what circumstances will a connection automatically be destroyed?

View configuration: https://github.com/HuolalaTech/page-spy-api/blob/master/room/local_room.go#L297-L323

  • If no SDK or debugging client enters the room after creation, it will be destroyed after 1 minute (in practical usage, this scenario does not exist);
  • If both the SDK and debugging client are disconnected, it will be destroyed after 1 minute;
  • If there is no data message interaction for 5 minutes, it will be destroyed;
  • If the connection lasts for more than 1 hour, it will be automatically destroyed;

Why in alipay miniprogram, I cannot access the global variables like 'my', 'getCurrentPages' when executing remote code?

Due to historical reasons, the alipay miniprogram has forbidden the access to global variables. You can change this setting in 2 ways:

Why are uploaded file logs missing?

  • Uploaded file logs are by default kept for a maximum of the latest 10GB and for 30 days, which can be customized by modifying the configuration.
  • Uploaded logs are stored in the 'log' directory within the running directory. When Docker is running, if the Docker is destroyed, the logs will also be lost. To persist logs, directory mapping -v ./log:/app/log -v ./data:/app/data can be used.
Clone this wiki locally