@connectrpc-tauri/transport

中文文档
0.1.5发布于 2026/11/07MIT OR Apache-2.0TypeScriptES Module零依赖构建来源已验证近 30 天下载 3823

通过 Tauri IPC 连接 RPC 运输( 命令 + 通道)

中文使用文档
文档目录14 节
  1. 为何没有重新执行连接而工作
  2. 使用量
  3. 它如何映射到IPC上
  4. 流出和后压
  5. 版式
  6. Protobuf 装订
  7. 正在验证
  8. 基准制定
  9. 为什么IPC的有效载荷会保持二进制
  10. 二进制 vs JSON 连接编码c
  11. 流出费用低于每条电文的过路费
  12. Unary 完全跳过 IPC
  13. 限制
  14. 捐款

将RPC连接到 Tauri IPC 上

A 类 连接RPC 搭载连接的运输 协议通过Tauri的IPC而不是HTTP。 网景是客户端Rust 主机服务,没有涉及HTTP服务器或端口.

所有四种方法都有效:无线、服务器流、客户端流和 师曰.

为何没有重新执行连接而工作

双方都已经暴露出字节平面的缝隙 所以这个箱子只是个穿梭机 双方:

  • 红宝石 ConnectRpcService 是一个 tower::Service<http::Request> 返回时 http::Response,所以它接受一个合成请求 从来没有触及过一个 接头.
  • 类型脚本 @connectrpc/connect/protocol-connect 出口 createTransport, (中文(简体) ), 需要一个 httpClient: UniversalClientFn - 一个平地 (request) => Promise<response> 穿过可触动的身体.

信件序列化 信封框架 压缩谈判 拖车, 错误映射,连接的同位素- GET 支持都来自现有的 运行时间.

这包起来 协议级别 createTransport没有 connect-web是因为 createConnectTransport使客户流动和 tidi 工作: 网络传输拒绝, 因为获取的 API 无法流出 a 请求正文,这里没有抓取被限制.

使用量

锈:

let router = Arc::new(Greeter).register(connectrpc::Router::new());

tauri::Builder::default()
    .plugin(connectrpc_tauri::serve(ConnectRpcService::new(router)))
    .run(tauri::generate_context!())
    .expect("failed to run app");

如果路由器依赖于 Tauri 设置时创建的状态, 则注册延迟 调度器先并初始化到设置钩子中 :

let deferred = connectrpc_tauri::DeferredDispatcher::new();

tauri::Builder::default()
    .plugin(connectrpc_tauri::serve(ConnectRpcService::new(deferred.clone())))
    .setup(move |app| {
        let router = router_from_app(app.handle());
        assert!(deferred.set(router).is_ok(), "ConnectRPC router initialized twice");
        Ok(())
    })
    .run(tauri::generate_context!())
    .expect("failed to run app");

类型脚本 :

import { createClient } from "@connectrpc/connect";
import { createTauriTransport } from "@connectrpc-tauri/transport";

const client = createClient(GreetService, createTauriTransport());
const { greeting } = await client.greet({ name: "World" });

能力文件必须给予插件权限, 否则每次呼叫都失败 与 Plugin not found数字 :

{
  "identifier": "default",
  "windows": ["main"],
  "permissions": ["core:default", "connectrpc-tauri:default"]
}

许可前缀是 Rust 箱子名称 。 Tauri 的 ACL 密钥插件 权限在 CARGO_PKG_NAME这样 PLUGIN_NAME 箱名必须等同; 在任何命令运行前,在ACL层中拒绝不匹配.

它如何映射到IPC上

独家电话绕过Tauri的IPC 其他的都用三个命令 和每个呼叫一个频道:

连接概念Tauri机制
联合请求和答复fetch("ipc-connect://…"),自定义 URI 方案
请求头 + 第一个正文块invoke("connect_rpc", …) 带原生出 ArrayBuffer
反应头(状况+信头)确定的价值 invoke
流化反应机构框架Channel<InvokeResponseBody> 携带生原生生物
客户- 流 / bodi 请求框架invoke("connect_rpc_send", …)
取消invoke("connect_rpc_cancel", …)从 AbortSignal
拖车带内,通过Connect自己的 EndStreamResponse 信封

信封是原生的 因为Tauri的IPC有效载荷是 无论是 原始字节或 JSON,从来没有两者,一个JSON有效载荷编码为每个字节一个数字. Protobuf 保存每个帧的单个原始缓冲,所以连接的字节保持二进制 结束到结束。 出于同样的原因,反应通道id在内部旅行 StartRequest 而不是作为JSON命令的论据.

使用频道而不是活动: Tauri 的活动系统是广播和 相对于一个呼叫来说没有顺序,所以它需要关联的id和去除a 频道提供免费服务.

流出和后压

分流是双向递增的,而不是缓冲. 请求机构是 一个 mpsc 支持 http_body::Body 那个 connect_rpc_send feed, 所以一个网页视图 写得快于处理器读取的时间 CHANNEL_DEPTH 块块—— 待处理 invoke 是后压信号.

在网景方面,信号是飞行中的信号。 信件生成时 一个是未完成的,被组合到下一个发送中,而不是每个使用一个 来回旅行 以及一个超过跳跃的制作人 MAX_PENDING_BYTES 等待它而不是缓冲溪流.

IPC路径上的一切是同音:所有三个命令都是 async fn,则 服务是按自己的任务驱动的,这样反应头就可以在返回之前返回 身体完好,反应泵通过合作排出 预算,所以内流不能垄断工人,也不能超过取消. 一个同步的锁 守护着一个散列地图, 从来没有在等待, 哪个 #![deny(clippy::await_holding_lock)] 强制执行.

版式

crates/connectrpc-tauri      Rust plugin
packages/transport           @connectrpc-tauri/transport
examples/greet-app           demo app exercising all four kinds
proto/                       transport envelopes + demo service
tools/protobuf-bindings      regenerates the crate's checked-in bindings

Protobuf 装订

两个软件包的生成绑定都经过检查,所以两个建筑都没有 不安装 npm 包 protoc 或者说 buf之后 改变计划,再生他们:

npm run generate                                       # TypeScript, with buf
mise exec -- cargo run --locked -p protobuf-bindings   # Rust, with the pinned protoc

hk check 如果需要再生成, 则失败 .

正在验证

cargo test -p connectrpc-tauri     # 12 tests over the real Connect runtime
npx vitest run                     # transport unit tests

# End-to-end, in a real webview. Exits nonzero on failure.
npm run build --workspace @connectrpc-tauri/transport
npm run build --workspace greet-app
GREET_APP_SELFTEST=1 cargo run --release -p greet-app --features custom-protocol

前两段将IPC桥自侧而上. 第三个是那个 证明 Tauri 的真实命令和频道携带协议: 它运行全部四个 在真实的网页视图中, 方法类型加上中流取消, 表示问候 每个RPC返回,打印一份记录,并有状态退出.

基准制定

npm run build --workspace @connectrpc-tauri/transport
npm run build --workspace greet-app
GREET_APP_BENCH=1 cargo run --release -p greet-app --features custom-protocol

这次是Tauri IPC能够为 相同的字节: 一个生 invoke 携带原生生物 invoke 和陶丽的 默认 JSON 参数, 空 Channel 用于流式响应,以及 invoke 每条消息用于流请求。 它运行在网络视图中,因为 这就是成本所在——Tauri IPC的昂贵部分正在穿越 webview 边界, 一个只使用 Rust 的基准永远不会支付 .

时间进行分批而不是按每个电话进行测量: WebKit 夹子 performance.now() 至 1ms,比整个RPC更粗.

在M系列的mac上,发布构建:

大小写这个运输最佳原始基线
unary, 16字节请求0.203毫米口径0.195m (1.04x) (中文(简体) )
unary, 4KiB 请求0.227毫米口径0.223ms (1.02x) (中文(简体) )
unary, 64KiB 请求0.363亿0.340 ms (1.07x) (1
服务器流, 100 x 16 字节0.797亿1.453ms(0.55x) (英语)
服务器流, 100 x 4KiB2.938亿7.875ms(0.37x) (英语)
客户端流, 100 x 16 字节1.156亿19.250毫米(0.06x)
客户端流, 100 x 4KiB2.250毫米口径21.500ms (0.10x) (中文(简体) )

上面的原始基线是原生的 invoke最快的移动方式 相同的字节用手写——客户端流行每条消息一个,即 一个手写客户端发送一个序列会做什么.

一个无名电话在手写的几分之一之内 invoke 已经不是了 完全通过Tauri的IPC。 一元请求是普通的 fetch 反对: ipc-connect:// 设置插件登记器,它跳过命令路由器, aCL的检查, 和原生包。 见 Unary 完全跳过 IPC。 。 。 .

两个流出方向都领先于手写式IPC,因为 每条消息支付一个网页视图过关:答复以 http_body 块 携带许多信封, 和请求合在一起 在出道。 见 流出费用低于每条电文的过路费。 。 。 .

为什么IPC的有效载荷会保持二进制

Tauri的IPC载荷是 无论是 原始字节或JSON,从来没有两者, 和一个JSON 有效载荷将字节编码为每字节一个JSON编号. 发送连接的字节为 JSON 命令参数费用, at 64KiB:

有效载荷64KiB请求
生字节( 我们做什么)0.375毫米口径
jSON 参数内的字节5.063亿米

也就是13x,它随大小而增长: 16字节时的同比 1.04x 和 2.4x at 4KiB, 因为爆炸是在编码中,而不是固定的成本. 一个JSON invoke 移动平原 字符串 长相快 (0. 375ms at 64KiB) – 但 a 连接消息是字节, 那就是应用的行 .

二进制 vs JSON 连接编码c

与上述问题不同的一个问题: useBinaryFormat 选择如何是 消息 被编码,而 IPC 有效载荷 无论是保持原始字节。 已经接近了 在这些大小下自由,二进制保留默认值 :

代码c16个B4个KiB64个KB
二进制0.258亿0.313毫米口径0.430毫米口径
贾森0.258亿0.309亿0.461亿

JSON只值得用于可读流量的编舞或代理视图 在进程跳动中,没有这种视图可获取,而且需要重新编码 更大的讯息.

流出费用低于每条电文的过路费

一个网页浏览器比它携带的字节要贵得多 所以两个都流着 所建立的方向发送数量比发送信息少.

回复不受协议约束: 连接的信封到达时是 http_body 块,这么多信息 在一个框架。 测量,100个流体 信件作为2个框架,而不是100个框架跨越 IPC 边界——其中天真 Channel 循环每次支付1个交叉.

请求需要帮助, 因为连接一次给客户端一个消息 . 等待一个 invoke 每条消息都会让一个客户端的调用 花费一整发 每条信件的行程——100条信件取出~19ms,准确跟踪手写 连环引用。 水泵现在集中了所有生产者 已经 连接到一个发送中, 将同样的100个信件连接到 ~1.2ms (英语).

"已经制作"是整个微妙的. 泵从不等待一块 因此,客户端正在等待的讯息 仍然立即独自离开。 这就是保持badi互动:a 及时分批的窗口会让对话陷入僵局,而下一个 请求取决于最后的答复.

Unary 完全跳过 IPC

Tauri 的 IPC 是一个命令路由器: 一个请求以一个 InvokeBody,与命令名称相匹配,然后对照ACL检查 回答过 无关紧要的连接电话不需要这些 它已经是一个HTTP 反对 tower::Service,而网页视图已经说 HTTP .

因此,插件注册了自己的URI方案, ipc-connect://,和闲电话 像个平地出海 fetchTauri的网页浏览管理器检查计划是否 在安装自己的处理器之前已经注册过, 因此它与 ipc:// 而不是替换它——每个股票插件继续工作.

跳过命令路由器也跳过什么使其他页面退出它. 每个 在 webview 中的框架可以达到自定义方案,包括另一个 iframe 来源:远程页面,或内容该应用程序服务于它自己的方案. Tauri的IPC拒绝那些有它只给主框的调取键的人. 这个 计划没有密钥,所以它检查请求的 Origin,该页面无法设置: 它只回答应用程序自己的页面( )tauri://localhost, (中文(简体) ), http://tauri.localhost 视窗和Android,或 devUrl )和名称 来源, 不 *,作为唯一可以读取答复的.

从无名电话中移除的是什么: 原生信封及其 编码/解码、命令名称发送、ACL权限查询、呼叫 注册和频道。 剩下的是接近身份图 http::Request 在,服务, http::Response 出局了,这就是为什么现在不必要 占手写土地的几分之一 invoke 而不是以上15%-20% 这个.

流能保持命令与渠道的路径. 计划响应器是一发 每个平台:它需要一个完整的响应值, 并在它下面 WKWebView 这样做 didReceiveResponse 然后是单曲 didReceiveData时 WebKitGTK 从一个完成的缓冲器建立它的流. 没有什么东西能推出第二秒 框架,所以通过这个方案来引导服务器流响应 一旦缓冲了整个系统就交付——这恰恰是源源不绝的 避开.

这个计划叫做 ipc-connect 而不是类似的东西 ipc+connect 因为Windows和Android wry重写 scheme://localhost 改为 http://scheme.localhost,使方案名称成为主机名标签. + 实值 在一个URI计划中是合法的,但是在主机名中没有,所以它可以工作在macOS和 Linux 并打破 Windows .

custom-protocol 塔里就是为捆绑的资产服务的原因 没有它, 每一建筑物——包括释放——载荷 devUrl 需求 npm run dev 运行中,因为Tauri从该特性中而不是从 货物简介.

限制

  • 网景 只收烂摊子. 网络浏览托管服务中的粗糙电话 超出范围.
  • 压缩是默认关闭的。 它将 CPU 用于在进程内缩小字节 跳出永不触碰网络; 旋钮在两侧被曝光 .
  • Android的IPC缺乏 InvokeBody::Raw 回到JSON数组。 A 类 基础64倒计时未执行。 这只影响流; 无效去 超过 ipc-connect:// 计划,不受影响.
  • 在 macOS 上已经验证出无源路径 。 计划登记和 处理Windows/Android主机名重写,但尚未在其中运行 这些平台上的CI.

捐款

从一个开始 讨论情况, (中文(简体) ), 不是拉动请求 一名数学维护者将审查该提案。 如果我们 决定执行它,一个维护者 或我们的AI代理将打开拉出 请求。 GitHub 将拉动请求创建限制在数学维护者 拥有写入、维护或管理权限的仓库协作者,加授权 维修人员.

数学执行提案时,执行拉动请求将 与讨论有关,并归功于提案的原作者.

见 捐款额 整个政策.

版本与发布记录

@connectrpc-tauri/transport 共发布 6 个版本,首次发布于 2026/08/18;过去 12 个月发布了 6 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.5latest2026/11/073 天前
0.1.42026/10/1427 天前
0.1.32026/09/022 个月前
0.1.22026/08/182 个月前
0.1.12026/08/182 个月前
0.1.02026/08/182 个月前

关于 @connectrpc-tauri/transport 的常见问题

@connectrpc-tauri/transport 是什么?

通过 Tauri IPC 连接 RPC 运输( 命令 + 通道)

如何安装 @connectrpc-tauri/transport?

在项目目录运行 npm install @connectrpc-tauri/transport,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@tauri-apps/api(^2.11.0)、@bufbuild/protobuf(^2.15.0)、@connectrpc/connect(^2.1.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@connectrpc-tauri/transport 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@connectrpc-tauri/transport 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@connectrpc-tauri/transport 可以商用吗?

@connectrpc-tauri/transport 使用 MIT OR Apache-2.0 许可。可在 MIT、Apache-2.0 中任选其一遵守。选择 MIT 时,宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@connectrpc-tauri/transport 的下载量有多少?

根据 npm 官方下载统计,@connectrpc-tauri/transport 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,823 次,日均约 127 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@connectrpc-tauri/transport 还在维护吗?

最新版本 0.1.5 发布于 2026/11/07(3 天前);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2026/08/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。