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

@wql00/xpra-vue-client

v0.1.0

Published

Xpra HTML5 client refactored for Vue / modern bundlers (Vite, Webpack 5).

Readme

@wql00/xpra-vue-client

Xpra HTML5 client refactored for Vue / modern bundlers (Vite, Webpack 5).

基于官方 xpra-html5 重构,适配 Vue 3 / Vite 工程化,将 worker、协议、窗口管理等模块以 ESM 形式导出,可直接 import 使用。

状态

0.1.0 — 早期版本。API 可能调整,已知存在遗留 DOM/全局耦合(见下方 已知限制)。

安装

npm install @wql00/xpra-vue-client interactjs
# 或
pnpm add @wql00/xpra-vue-client interactjs

interactjs 是 peer dependency,需自行安装(用于窗口拖拽/缩放)。

要求

  • 打包器:Vite ≥ 4 或 Webpack 5(必须支持 new Worker(new URL('./xxx.worker.ts', import.meta.url), { type: 'module' }) 语法)
  • 浏览器:现代浏览器(Chrome/Edge/Firefox/Safari 最新版)
  • TypeScript:≥ 5.0(可选,包内置 .d.ts 类型声明)

快速开始

1. 准备容器元素

xpra 客户端会通过 document.getElementById(containerId) 查找容器,并将远程桌面渲染到其中。

<!-- index.html 或 Vue 模板 -->
<div id="screen" style="width: 100vw; height: 100vh;"></div>

2. 创建客户端并连接

import { XpraClient } from '@wql00/xpra-vue-client';

const client = new XpraClient('screen'); // 容器元素 id

// 连接参数
client.host = '1.2.3.4';
client.port = 10000;
client.path = '/';
client.username = 'foo';
client.passwords = ['bar'];
client.ssl = true; // wss://,false 则用 ws://

// 可选:加密
// client.encryption = 'AES'

// 可选:编码
// client.encoding = 'jpeg'

// 回调
client.on_connection_progress = (msg, details, progress) => {
  console.log(`[${progress}%] ${msg}`);
};
client.on_connect = () => console.log('connected');
client.callback_close = (reason) => console.log('disconnected:', reason);

// 启动
client.init();
client.connect();

3. 断开连接

client.reconnect = false;
client.close();

API

XpraClient

主类,从 '@wql00/xpra-vue-client' 导出。

构造函数

new XpraClient(containerId: string)
  • containerId:HTML 容器元素的 id(不是元素本身)

主要属性

| 属性 | 类型 | 说明 | | ------------ | ---------- | ----------------------------------------- | | host | string | 服务器主机 | | port | number | 服务器端口 | | path | string | WebSocket 路径,默认 '/' | | username | string | 用户名 | | passwords | string[] | 密码(数组,支持多密码轮询) | | ssl | boolean | 是否使用 wss:// | | encryption | string | 加密方式(如 'AES') | | encoding | string | 图像编码(如 'jpeg''png''rgb') | | reconnect | boolean | 是否自动重连 |

主要方法

| 方法 | 说明 | | ----------- | --------------------------------- | | init() | 初始化(在 connect() 之前调用) | | connect() | 建立连接 | | close() | 关闭连接 |

回调

| 回调 | 说明 | | ------------------------------------------------ | ---------------- | | on_connect() | 连接成功 | | on_open() | WebSocket 已打开 | | callback_close(reason: string) | 连接关闭 | | on_connection_progress(msg, details, progress) | 连接进度 |

类型

import type { XpraOptions, ClientOptions, ClientCallbacks } from '@wql00/xpra-vue-client';

XpraOptions 是简化的连接参数接口:

interface XpraOptions {
  host: string;
  port: number;
  path: string;
  username: string;
  password: string;
  ssl?: boolean;
  encryption?: string;
  encoding?: string;
}

Vue 3 集成示例

虽然本包不包含 Vue 组件(保持框架无关),但可以很轻松地封装成 composable:

// useXpra.ts
import { ref, onUnmounted } from 'vue';
import { XpraClient, type XpraOptions } from '@wql00/xpra-vue-client';

export function useXpra(containerId: string) {
  const client = ref<XpraClient | null>(null);
  const status = ref<'idle' | 'connecting' | 'connected' | 'disconnected'>('idle');

  function connect(options: XpraOptions) {
    if (client.value) client.value.close();
    const c = new XpraClient(containerId);
    c.host = options.host;
    c.port = options.port;
    c.path = options.path;
    c.username = options.username;
    c.passwords = [options.password];
    c.ssl = options.ssl ?? false;
    if (options.encryption) c.encryption = options.encryption;
    if (options.encoding) c.encoding = options.encoding;

    c.on_connect = () => {
      status.value = 'connected';
    };
    c.callback_close = () => {
      status.value = 'disconnected';
    };
    c.on_connection_progress = () => {
      status.value = 'connecting';
    };

    client.value = c;
    c.init();
    c.connect();
  }

  function disconnect() {
    client.value?.close();
    client.value = null;
    status.value = 'disconnected';
  }

  onUnmounted(disconnect);

  return { client, status, connect, disconnect };
}
<!-- XpraViewer.vue -->
<template>
  <div :id="containerId" style="width: 100%; height: 100%;"></div>
</template>

<script setup lang="ts">
  import { useXpra } from './useXpra';

  const containerId = 'screen';
  const { status, connect } = useXpra(containerId);

  connect({
    host: '1.2.3.4',
    port: 10000,
    path: '/',
    username: 'foo',
    password: 'bar',
    ssl: true,
  });
</script>

工作原理

Worker 加载

本包内部使用 3 个 Web Worker:

  • protocol.worker.ts — 协议层(rencode/lz4/brotli 解码、加密)
  • decode.worker.ts — 图像解码
  • offscreen.worker.ts — 离屏渲染

通过 Vite/Webpack 5 的 new Worker(new URL('./workers/*.worker.ts', import.meta.url), { type: 'module' }) 语法加载。这意味着运行时入口指向 src/index.ts 源码(而非预编译的 dist/index.mjs),由消费方的打包器编译 worker。dist/ 下的 JS 产物仅供 CJS 环境或不使用 worker 的场景使用。

Brotli 解码器

包入口(src/index.ts)会自动将 vendored 的 BrotliDecode 注册到 self 全局,消费方无需手动处理。

已知限制(TODO)

以下为官方 xpra-html5 遗留的耦合,尚未完全解耦,计划在后续版本逐步清理:

  1. DOM ID 耦合Client.ts / Window.ts 直接通过 ID 访问 DOM 元素(#screen#float_menu#pasteboard#window_preview#dpi#favicon 等)。若宿主页面没有这些元素,相关功能会静默失败。
  2. 全局耦合MenuCustom.tsClient.ts 部分代码依赖 window.clientwindow.toggle_float_menuwindow.doNotification 等全局变量。
  3. 动态生成的 DOM IDWindow.ts 内部会创建 head${wid}title${wid}windowicon${wid} 等元素,与宿主页面可能冲突。

临时方案:在宿主页面预留必要的容器元素(至少 #screen)。

开发

# 安装依赖
pnpm install

# 构建(生成 dist/)
pnpm --filter @wql00/xpra-vue-client build

# 类型检查
npx tsc --noEmit --project packages/xpra-html5/tsconfig.json

License

MPL-2.0

This package is based on the xpra-html5 project (MPL-2.0).