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 🙏

© 2026 – Pkg Stats / Ryan Hefner

sigillum-js

v1.3.0

Published

A session recording library for user behavior replay and bug reproduction

Readme


它做什么

录制完整的用户会话,让你可以回放用户的每一步操作。数据自管理。

安装

npm install sigillum-js
yarn add sigillum-js
# or
pnpm add sigillum-js

快速开始

import { getRecorder } from 'sigillum-js';

const recorder = getRecorder({
  onUpload: async (data) => {
    await fetch('/api/recordings', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    return { success: true };
  },
});

recorder.start();

// 之后 — 停止并上传
await recorder.stop();

就这样。录制器自动捕获所有用户操作 —— 鼠标移动、滚动、输入和路由跳转。调用 stop() 后,数据通过你的 onUpload 回调上传。

纯本地模式(不上传)

适用于用户手动导出录制数据的调试场景:

const recorder = getRecorder({ debug: true });

recorder.start();
// ... 用户复现 bug ...
await recorder.stop();

const data = recorder.exportRecording();
downloadAsJson(data); // 你的下载工具函数

框架集成

| 框架 | 导入路径 | 主要导出 | |------|----------|----------| | 原生 JS | sigillum-js | getRecorder(), resetRecorder(), isRecorderInitialized() | | React 16.8+ | sigillum-js/react | useSessionRecorder(), useAutoRecord() | | Vue 3+ | sigillum-js/vue | createSigillumPlugin(), useSessionRecorder(), useAutoRecord() |

import { useAutoRecord } from 'sigillum-js/react';

function App() {
  const { status, sessionId, addTag, identify } = useAutoRecord({
    onUpload: async (data) => {
      await fetch('/api/recordings', { method: 'POST', body: JSON.stringify(data) });
      return { success: true };
    },
  });

  identify('user-123', { plan: 'pro' });

  return <div>状态: {status}</div>;
}
// main.ts
import { createApp } from 'vue';
import { createSigillumPlugin } from 'sigillum-js/vue';

const app = createApp(App);
app.use(createSigillumPlugin({
  onUpload: async (data) => {
    await fetch('/api/recordings', { method: 'POST', body: JSON.stringify(data) });
    return { success: true };
  },
  autoStart: true,
}));
app.mount('#app');
<script setup>
import { inject, onUnmounted, ref } from 'vue';
import { useAutoRecord } from 'sigillum-js/vue';

const { status, sessionId, addTag } = useAutoRecord(inject, onUnmounted, { ref });
</script>

<template>
  <div>状态: {{ status.value }}</div>
</template>

回放 UI

内置 React 回放组件:

import { ReplayPlayer, ReplayPage } from 'sigillum-js/ui';

<ReplayPlayer data={recordingData} />

// 完整页面(含会话信息)
<ReplayPage data={recordingData} showInfo={true} />

通过 config 定制回放行为。常用的 rrweb Replayer 选项已作为一级字段提供;其他选项可通过 replayerConfig 透传。

<ReplayPlayer
  data={recordingData}
  config={{
    speed: 2,
    autoPlay: true,
    showController: true,
    skipInactive: true,

    // rrweb Replayer 选项
    UNSAFE_replayCanvas: true,   // 录制时启用了 recordCanvas 则需要开启
    mouseTail: false,            // 隐藏鼠标轨迹
    pauseAnimation: true,        // 暂停时冻结 CSS 动画
    useVirtualDom: false,
    liveMode: false,
    triggerFocus: true,
    insertStyleRules: ['body { background: #fff; }'],
    unpackFn: (e) => e,          // 与录制端的 packFn 配对使用

    // 透传其他未列出的 rrweb Replayer 原生选项
    replayerConfig: {
      // 例如 blockClass、loadTimeout、showWarning 等
    },
  }}
/>

注意eventswidthheight 由组件内部管理,不可通过 configreplayerConfig 覆盖。

API 参考

const recorder = getRecorder(options);

// 生命周期
recorder.start();
await recorder.stop();
recorder.pause();
recorder.resume();

// 数据
recorder.exportRecording();     // 停止后导出(事件 + 元数据 + 行为摘要)
recorder.clearRecording();      // 释放内存

// 标记 & 用户身份
recorder.addTag(name, data);
recorder.identify(userId, traits?);

// 状态
recorder.getStatus();           // 'idle' | 'recording' | 'paused' | 'stopped'
recorder.getSessionId();
recorder.getEventCount();
recorder.getEstimatedSize();
recorder.getSummary();          // { clickCount, inputCount, scrollCount, routeChanges, ... }

// 销毁
recorder.destroy();
resetRecorder();
const recorder = getRecorder({
  // 上传(可选 — 不提供则为纯本地模式)
  onUpload: async (data) => { return { success: true }; },

  // 字段映射(适配后端数据结构)
  fieldMapping: [['sessionId', 'id'], ['events', 'content', JSON.stringify, JSON.parse]],
  beforeUpload: (data) => ({ ...data, userId: getCurrentUserId() }),

  // 启用条件
  enabled: () => user.isVIP || Math.random() < 0.1,

  // 防崩溃缓存
  cache: { enabled: true, saveInterval: 5000, maxItems: 10, maxAge: 604800000 },

  // 分段上传(长录制场景)
  chunkedUpload: { enabled: true, interval: 60000 },
  onChunkUpload: async (chunk) => { return { success: true }; },

  // 回调
  onEventEmit: (event, count) => {},
  onError: (error) => {},
  onStatusChange: (status, prev) => {},

  // 限制
  maxEvents: 50000,
  maxDuration: 1800000,  // 30 分钟
  maxRetries: 3,

  // 隐私(遮盖输入、屏蔽元素等)
  rrwebConfig: {
    privacy: {
      blockSelector: '.credit-card-form, [data-private]',
      maskAllInputs: true,
    },
    slimDOMOptions: 'all',
  },

  // 其他
  uploadOnUnload: true,
  beaconUrl: '/api/beacon',
  debug: false,
});

兼容性

| 浏览器 | 版本 | |--------|------| | Chrome | 64+ | | Firefox | 69+ | | Safari | 12+ | | Edge | 79+(Chromium) | | iOS Safari | 12+ | | IE | 不支持 |

| 框架 | 版本 | 导入路径 | |------|------|----------| | React | 16.8+ | sigillum-js/react | | Vue | 3.0+ | sigillum-js/vue | | Next.js | 12+ | 通过 React 集成 | | Nuxt | 3+ | 通过 Vue 集成 |

推荐搭配

如果你还需要 错误追踪、日志管理和性能监控,可以看看 aemeath-js —— 轻量级、插件化的前端日志 & 监控 SDK。

sigillum-js(会话录制)+ aemeath-js(日志 & 监控)= 完整的前端可观测性方案,所有数据都在你自己的服务器上。

反馈

欢迎提交 Issue 和功能建议!请到 Issues 页面反馈。

许可证

MIT © TieriaSail


本项目使用 AI 辅助开发。