ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Rivet Actors 全栈实战:用 Hono 后端与 React 前端构建类型安全的实时应用

Rivet Actors 全栈实战:用 Hono 后端与 React 前端构建类型安全的实时应用 Rivet Actors 全栈实战用 Hono 后端与 React 前端构建类型安全的实时应用【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors本文以仓库examples/hono-react示例为主体讲解如何用 RivetKit 的actor()/setup()定义有状态 Actor用 Hono 承载 HTTP 路由与 React 静态资源再通过rivetkit/react的useActor/useEvent在浏览器端实时订阅 Actor 事件。读完本文你将掌握单一代码库 共享类型 双向实时通信的 Rivet Actors 全栈开发模式并能直接复刻出可运行的计数服务。示例概览一个文件看懂全栈结构examples/hono-react是仓库中展示全栈full-stack集成的最小可运行示例后端是 Hono Web 框架前端是 ReactVite 构建业务逻辑与状态管理完全由 Rivet Actor 承担前后端共享同一份 TypeScript 类型定义。示例的目录结构如下相对仓库根目录examples/hono-react/ ├── frontend/ # React 前端App.tsx、main.tsx ├── src/ │ ├── index.ts # Actor 定义 registry 启动入口 │ └── server.ts # Hono HTTP 服务器 ├── index.html # Vite 入口 HTML ├── package.json # 依赖与 npm scripts ├── tsconfig.json # 前后端统一 TS 配置 ├── turbo.json # Turborepo 任务依赖声明 └── vite.config.ts # Vite 构建与开发代理配置从依赖清单package.json可以看出它的技术选型运行时rivetkit^2.3.17提供actor、event、setup等 Actor 原语hono^4.7.0提供 HTTP 路由前端react/react-dom^18.2.0与rivetkit/react^2.3.17提供createRivetKit、useActor等 React hooks开发工具tsx负责以 watch 模式运行 TS 服务端vite负责前端开发服务器concurrently将两者并行拉起vitest用于测试。值得注意README 中提到的 Actor 定义位于src/backend/registry.ts而在当前仓库中实际路径为 src/index.ts未拆分 backend 子目录。本文以仓库实际源码为准。快速开始三步跑起全栈示例README 给出了标准启动流程结合本仓库实际环境整理如下# 克隆仓库若尚未克隆 git clone https://gitcode.com/GitHub_Trending/riv/actors.git cd riv/actors/examples/hono-react # 安装依赖仓库使用 pnpm workspace也可用 npm install npm install # 并行启动 Hono 服务端与 Vite 前端 npm run devdev脚本定义在 package.json 中dev: concurrently -n server,vite \tsx --watch src/index.ts\ \vite\它同时做两件事tsx --watch src/index.ts以 watch 模式运行 Actor 入口文件变更后自动重启vite启动 Vite 开发服务器提供 React 前端热更新。此外还有dev:server仅启动服务端、buildVite 构建、start以tsx直接运行用于生产、check-typestsc --noEmit类型检查与testvitest 运行测试等脚本可在开发与部署阶段按需选用。启动后Rivet 运行时默认监听http://localhost:6420见下文 Vite 代理配置浏览器打开 Vite 提供的地址即可看到计数器界面。Actor 定义actoreventsetup三件套示例的核心业务逻辑全部浓缩在 src/index.ts 中import { actor, event, setup } from rivetkit; export const counter actor({ state: { count: 0 }, events: { newCount: eventnumber(), }, actions: { increment: (c, x: number) { c.state.count x; c.broadcast(newCount, c.state.count); return c.state.count; }, }, }); export const registry setup({ use: { counter }, }); registry.start();这段代码完整覆盖了 Rivet Actor 的三个核心概念1. 有状态 Actorstatestate: { count: 0 }声明了 Actor 的持久状态。状态由 Rivet 运行时管理跨请求保留这也是有状态工作负载stateful workloads的基础。在 actor() 定义中可以看到actor()接收一个经过ActorConfigSchema校验的配置对象泛型参数涵盖TState、TConnParams、TEvents、TActions等从而在编译期约束状态、事件与动作的类型。2. 类型化事件eventT()newCount: eventnumber()声明了一个携带number负载的实时事件。动作内部通过c.broadcast(newCount, c.state.count)向所有已连接客户端广播新计数官方文档中说明broadcast面向使用.connect()建立的连接事件通道独立于低层 WebSocket。eventT在 schema.ts 中定义配合 TypeScript 推断事件名与负载类型天然联动。3. 动作actionsincrement接收上下文c与参数x修改状态、广播事件并返回新值。动作默认并行执行且极轻量官方文档 actions.mdx 说明其可通过 HTTP 或 WebSocket 调用需要并发控制时可升级为队列queues。注意客户端调用动作是异步的即使动作本身是同步函数也需要await。4. Registry 与启动setup({ use: { counter } })将 Actor 注册进 registryregistry.start()启动运行时。registry 的类型typeof registry会被服务端客户端和 React hooks 复用是全栈类型安全的枢纽。Hono 后端HTTP 端点 Rivet 请求转发服务端逻辑在 src/server.tsimport { Hono } from hono; import { createClient } from rivetkit/client; import { registry } from ./index.ts; const client createClienttypeof registry(); const app new Hono(); // Example HTTP endpoint app.post(/increment/:name, async (c) { const name c.req.param(name); const counter client.counter.getOrCreate(name); const newCount await counter.increment(1); return c.text(String(newCount)); }); app.all(/api/rivet/*, (c) registry.handler(c.req.raw)); export default app;这里有三个值得深入的点1. 类型安全的客户端createClienttypeof registry()客户端以 registry 类型为泛型参数于是client.counter自动获得counterActor 的类型信息——getOrCreate、increment的签名和返回值全部可被编译器校验不存在手写接口对齐的负担。这正是示例强调的前后端共享类型落地点createClient与ActorDefinition的类型传播链路在 client 模块 中定义。2. 按 key 取用 ActorgetOrCreate(name)Rivet Actor 以 key 区分实例。getOrCreate语义是存在则取、不存在则创建因此每个不同的name都会获得独立的counter实例与独立的状态。前端输入框切换名称实际上就是在不同 Actor 实例之间切换。3. 一键暴露全部 Actor APIregistry.handler(c.req.raw)这一行把 Hono 收到的请求原始 Request 交给 Rivet registry 处理相当于把 Actor 的 actions 全部通过/api/rivet/*路径以 HTTP 形式暴露同时 WebSocket 握手也由此接管。这样就不需要为每个 action 手写路由业务逻辑保持在 Actor 内部HTTP 层只是薄薄的传输壳。React 前端createRivetKituseActoruseEvent前端在 frontend/App.tsx 中消费 Actorimport { createRivetKit } from rivetkit/react; import { useState } from react; import type { registry } from ../src/index.ts; const { useActor } createRivetKittypeof registry(http://localhost:6420); function App() { const [count, setCount] useState(0); const [counterName, setCounterName] useState(test-counter); const counter useActor({ name: counter, key: [counterName], }); counter.useEvent(newCount, (x: number) setCount(x)); const increment async () { await counter.connection?.increment(1); }; return ( div h1Counter: {count}/h1 input typetext value{counterName} onChange{(e) setCounterName(e.target.value)} placeholderCounter name / button onClick{increment}Increment/button /div ); } export default App;1.createRivetKittypeof registry(url)由rivetkit/react包提供的工厂函数内部创建 Rivet 客户端并返回一组 React hooks实现见 react/src/mod.ts。它同样以typeof registry为泛型因此 hooks 天然感知所有 Actor 的名称、key 结构、actions 与 events 签名。2.useActor({ name, key })连接指定 Actor 实例并订阅其状态。其实现基于getOrCreateActor与useStorereact/src/mod.ts相同 opts 会复用同一 Actor 实例组件挂载时自动mount()建立连接卸载时自动清理。返回对象包含handle、connection、connStatus、error等字段UseActorState 类型。3.counter.useEvent(newCount, cb)以 hooks 方式订阅 Actor 广播的实时事件事件回调通过useRef保持最新、由useEffect挂载与清理react/src/mod.ts。当后端increment里执行c.broadcast(newCount, ...)时前端回调被触发setCount更新 UI——这就是不轮询、无外部 pub-sub的实时通道。4. 调用动作counter.connection?.increment(1)通过已建立的连接直接调用incrementaction编译期即可校验参数与返回类型。由于 action 调用是异步的这里使用await。前端入口 frontend/main.tsx 与 index.html 是标准的 React 挂载流程无特殊逻辑。开发期联通Vite 代理与端口约定前后端在开发期通过 vite.config.ts 中的代理联通server: { clearScreen: false, proxy: { /actors: { target: http://localhost:6420, ws: true }, /metadata: { target: http://localhost:6420 }, /health: { target: http://localhost:6420 }, }, },三个路径前缀/actors、/metadata、/health被代理到localhost:6420——即 Rivet 运行时默认监听的端口/actors开启了ws: true允许 WebSocket 升级这是useActor建立实时连接、接收newCount事件的关键浏览器端代码以http://localhost:6420直连见 App.tsx 的createRivetKit参数而静态资源由 Vite 提供两者在开发期并存互不干扰。build脚本将产物输出到public目录build.outDir: public生产部署时由 Hono 或静态服务器统一托管。端到端数据流回顾把上述模块串起来一次点击按钮的完整链路是React 按钮触发counter.connection?.increment(1)通过 WebSocket经 Vite 代理转发到localhost:6420调用counterActor 的incrementactionRivet 运行时执行incrementc.state.count x更新持久状态随后c.broadcast(newCount, count)向所有连接广播新值前端counter.useEvent(newCount, ...)收到事件setCount触发 React 重渲染同时任意 HTTP 客户端如curl -X POST /increment/foo经由 Hono 路由app.post(/increment/:name)走client.counter.getOrCreate(name).increment(1)完成同一操作——两种调用方式共享同一份状态。这一模式正是 Rivet Actors 面向 AI Agent、协作应用与持久化执行场景的典型形态业务状态收敛在 Actor 内HTTP 与 WebSocket 都只是访问通道前端通过类型安全的 hooks 获得实时同步。相关文档与延伸阅读本示例涉及的核心能力在仓库官方文档中均有系统讲解可继续深入Actions动作动作的定义、嵌套动作、三种调用方式前端createClient/ 后端registry.handler/ Actor 间c.client()与错误处理State状态Actor 状态的生命周期与更新语义Events实时事件c.broadcast全量广播、conn.send定向发送与客户端订阅方式Connections连接.connect()持久连接的建立与维护快速上手从零开始编写第一个 Actor 的完整流程。若要在自己的项目中使用可参照 turbo.json 声明build对rivetkit/react#build与rivetkit#build的依赖确保本地开发时 SDK 包先行构建。本示例以 MIT 协议开源可直接作为脚手架改造使用。【免费下载链接】actorsRivet Actors are the primitive for stateful workloads. Built for AI agents, collaborative apps, and durable execution.项目地址: https://gitcode.com/GitHub_Trending/riv/actors创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表