SpacetimeDB React 快速入门:5 分钟用spacetime dev搭建前后端实时应用
【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB
本篇基于 SpacetimeDB 1.12.0 版本的 React 快速入门文档,完整演示如何用一条spacetime dev命令同时拉起本地 SpacetimeDB 服务器、发布服务端模块、生成 TypeScript 类型绑定并启动 React 开发服务器。读者完成后将掌握 React 客户端与 SpacetimeDB 模块的完整开发闭环:定义表与归约器(Reducer)、在 React 组件中响应式读写数据,以及用 CLI 直接调用与验证数据。文中所有代码与结构均以本仓库 templates/react-ts 模板为实证来源。
前置条件:Node.js 与 SpacetimeDB CLI
开始前需要准备两样东西:
- Node.js 18+:React 客户端与 TypeScript 绑定生成依赖现代 Node 运行时;
- SpacetimeDB CLI:负责启动本地服务器、发布模块、生成绑定、调用归约器等一系列操作。
CLI 是贯穿整个开发流程的核心工具。本仓库中提供了跨平台安装脚本 crates/update/spacetime-install.sh(Linux/macOS)与 crates/update/spacetime-install.ps1(Windows),可据此完成安装。安装完成后,在终端执行spacetime --version确认命令可用。
创建项目:一条命令启动前后端
在空目录中执行:
spacetime dev --template react-ts my-spacetime-app--template react-ts指定使用 React + TypeScript 模板,my-spacetime-app为项目名称。该命令会依次完成四件事:
- 启动本地 SpacetimeDB 服务器;
- 发布你的服务端模块;
- 为模块生成 TypeScript 类型绑定(写入
module_bindings/); - 启动 React 开发服务器。
对应模板的脚本定义可见 templates/react-ts/package.json:spacetime:generate执行spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb生成绑定,spacetime:publish:local执行spacetime publish --module-path server --server local发布到本地服务器。spacetime dev正是将这一系列步骤串联起来的开发模式命令。
打开你的应用:访问 localhost:5173
开发服务器启动后,浏览器访问 http://localhost:5173 即可看到运行中的应用。模板自带一个已连接 SpacetimeDB 的基础 React 应用:页面上会显示连接状态(Connected / Disconnected)、一个"Add Person"输入表单,以及当前数据库中的所有人名单。
项目结构解析
my-spacetime-app/ ├── spacetimedb/ # 你的 SpacetimeDB 服务端模块 │ └── src/ │ └── index.ts # 服务端逻辑:表定义与归约器 ├── src/ # React 前端 │ ├── main.tsx # 连接 SpacetimeDB 的入口 │ ├── App.tsx # 主界面组件 │ └── module_bindings/ # 自动生成的类型绑定(勿手改) ├── package.json ├── index.html ├── tsconfig.json └── vite.config.ts对照本仓库中的 templates/react-ts 目录,可以看到完整的模板布局:服务端模块位于spacetimedb/src/index.ts,前端源码位于根目录src/下,其中module_bindings/存放由 CLI 自动生成、与模块 schema 强绑定的类型文件。编辑spacetimedb/src/index.ts来添加表和归约器,编辑src/App.tsx来构建 UI。
服务端模块:表(Table)与归约器(Reducer)
打开spacetimedb/src/index.ts,这是整个应用的"大脑"。模板定义了一张person表和两个归约器add、sayHello,完整的模板代码见 templates/react-ts/spacetimedb/src/index.ts:
import { schema, table, t } from 'spacetimedb/server'; const spacetimedb = schema({ person: table( { public: true }, { name: t.string(), } ), }); export default spacetimedb; export const add = spacetimedb.reducer( { name: t.string() }, (ctx, { name }) => { ctx.db.person.insert({ name }); } ); export const sayHello = spacetimedb.reducer(ctx => { for (const person of ctx.db.person.iter()) { console.info(`Hello, ${person.name}!`); } console.info('Hello, World!'); });代码里两个核心概念需要理解透彻:
- 表(Table)存储数据:
table({ public: true }, { name: t.string() })声明一张公开可读的表,public: true表示所有客户端都可订阅读取;t.string()是 SpacetimeDB 的类型构造器,用于声明字段类型(还有t.u32()、t.bool()、t.array()等,详见核心概念文档中的列类型说明)。schema(...)将表聚合为一个模块 schema 并默认导出。 - 归约器(Reducer)是唯一写入口:
spacetimedb.reducer(...)声明一个可被客户端远程调用的函数,客户端只能通过归约器修改数据——这是 SpacetimeDB 事务模型的基石。add接收{ name: t.string() }参数,通过ctx.db.person.insert({ name })插入一行;sayHello通过ctx.db.person.iter()遍历表中所有行并打印问候语。
除了归约器,模板还演示了模块生命周期钩子:spacetimedb.init(...)在模块首次发布时调用,clientConnected/clientDisconnected分别在客户端连接/断开时触发。这些钩子可用于初始化种子数据或做连接统计。
客户端连接:main.tsx 与 SpacetimeDBProvider
React 客户端与服务器的连接在 templates/react-ts/src/main.tsx 中建立,关键片段如下:
const HOST = import.meta.env.VITE_SPACETIMEDB_HOST ?? 'ws://localhost:3000'; const DB_NAME = import.meta.env.VITE_SPACETIMEDB_DB_NAME ?? 'react-ts'; const TOKEN_KEY = `${HOST}/${DB_NAME}/auth_token`; const connectionBuilder = DbConnection.builder() .withUri(HOST) .withDatabaseName(DB_NAME) .withToken(localStorage.getItem(TOKEN_KEY) || undefined) .onConnect(onConnect) .onDisconnect(onDisconnect) .onConnectError(onConnectError);要点拆解:
- 连接地址:默认通过 WebSocket 协议连接
ws://localhost:3000(spacetime dev启动的本地服务器默认端口),数据库名默认为react-ts;两者均可用 Vite 环境变量VITE_SPACETIMEDB_HOST/VITE_SPACETIMEDB_DB_NAME覆盖; - 身份令牌持久化:连接成功后回调会把服务器签发的
token存入localStorage,下次打开页面自动携带,实现身份复用; - Provider 注入:构建好的
connectionBuilder通过<SpacetimeDBProvider connectionBuilder={...}>提供给整个 React 组件树,所有组件都能通过 Hooks 访问连接与数据。
DbConnection、SubscriptionBuilder等类型均由module_bindings/index.ts自动生成并携带模块级类型信息(详见 templates/react-ts/src/module_bindings/index.ts),因此连接层天然具备端到端类型安全。
React 组件中的响应式数据:useTable 与 useReducer
前端界面的核心逻辑在 templates/react-ts/src/App.tsx 中,它演示了 SpacetimeDB React SDK 的三个关键 Hook:
const conn = useSpacetimeDB(); const { isActive: connected } = conn; // 订阅数据库中的所有 person const [people] = useTable(tables.person); const addReducer = useReducer(reducers.add); const addPerson = (e: React.FormEvent) => { e.preventDefault(); if (!name.trim() || !connected) return; addReducer({ name: name }); // 调用 add 归约器写入数据 setName(''); };useSpacetimeDB()返回连接对象,conn.isActive指示当前是否已连接,据此禁用表单按钮,避免离线提交;useTable(tables.person)订阅person表:tables与reducers来自自动生成的绑定(见 templates/react-ts/src/module_bindings/index.ts),useTable返回的数组是响应式的——服务器数据变化会立即触发 React 重渲染,列表people.map(...)随之自动更新,无需手动拉取或轮询;useReducer(reducers.add)返回一个带类型的归约器调用函数,参数对象{ name }与模块中add的入参 schema 完全一致,编译期即可校验。
这就是 SpacetimeDB "订阅即同步" 的客户端体验:客户端声明订阅哪些表(useTable),服务器主动推送增量数据,UI 始终保持最新。
自动生成的类型绑定:module_bindings
src/module_bindings/下的文件全部由 CLI 自动生成,文件头注释明确警告 "EDITS TO THIS FILE WILL NOT BE SAVED",因此永远不要手动修改。以 person_table.ts 为例,它与服务端person表一一对应:
export default __t.row({ name: __t.string(), });修改服务端spacetimedb/src/index.ts中的表或归约器定义后,通过模板脚本重新生成绑定即可:
npm run spacetime:generate # 等价于 spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb重新生成后,tables.person与reducers.add的类型会自动跟上服务端的最新 schema。
用 CLI 直接调用与验证
另开一个终端,无需写任何客户端代码即可验证服务端逻辑(以下以本地开发库为例,若模块发布为多库部署,可在spacetime call/sql/logs后追加<database-name>指定数据库):
# 调用 add 归约器插入一个人 spacetime call <database-name> add Alice # 用 SQL 查询 person 表 spacetime sql <database-name> "SELECT * FROM person" name --------- "Alice" # 调用 say_hello 向所有人问好 spacetime call <database-name> say_hello # 查看模块日志 spacetime logs <database-name> 2025-01-13T12:00:00.000000Z INFO: Hello, Alice! 2025-01-13T12:00:00.000000Z INFO: Hello, World!四条命令构成完整的"写 → 读 → 执行 → 观察"验证闭环:spacetime call直接触发归约器,spacetime sql以 SQL 形式即时查询表数据,spacetime logs拉取模块侧console.info输出的日志。注意归约器名称以模块中注册的名字为准(模板代码中为sayHello,快速入门文档示例中注册为say_hello),调用时使用实际注册名即可。这些 CLI 子命令的完整参数说明可在 crates/cli/src 的源码中找到。
下一步:继续深入
- 跟随完整的 Chat App 教程 构建一个更完整的聊天应用,覆盖多人实时交互场景;
- 查阅 TypeScript SDK 参考文档,了解
DbConnection、SubscriptionBuilder、事件上下文等全部 API; - 在本仓库 templates 目录下探索
react-ts之外的其他模板(如 chat-react-ts、hangman-react-ts),它们基于相同的模块 + 客户端结构,展示了更丰富的应用形态。
【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考