news 2026/9/13 18:57:04

SpacetimeDB Bun 快速上手指南:5 分钟构建 TypeScript 实时多人在线应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpacetimeDB Bun 快速上手指南:5 分钟构建 TypeScript 实时多人在线应用

SpacetimeDB Bun 快速上手指南:5 分钟构建 TypeScript 实时多人在线应用

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

本篇指南基于 SpacetimeDB 官方 Bun 快速入门文档,结合仓库内 templates/bun-ts 模板的完整源码,从项目脚手架创建、服务端模块编写、Bun 客户端连接与交互,到spacetimeCLI 调试验证,逐步带你掌握用 SpacetimeDB 与 Bun 构建"数据库即服务端"实时应用的完整实战流程。读完本文,你将能够独立创建、运行并调试一个完整的 SpacetimeDB + Bun 全栈应用。

适用前提:本指南针对 Bun 运行时(当前模板要求bun^1.3.2),使用 TypeScript 编写服务端与客户端逻辑;你无需预先掌握 SpacetimeDB 的内部实现,只需具备基础的 TypeScript 与命令行使用经验即可。

前置条件

开始之前,请确保本机已安装以下两个工具:

  • Bun:一个集运行时、包管理器、构建工具于一体的 JavaScript/TypeScript 运行时。访问 bun.sh 按其官方安装方式安装。
  • SpacetimeDB CLI:SpacetimeDB 的命令行工具,用于创建项目、启动本地服务器、发布模块与查询数据,参考官方安装页(仓库 crates/cli 即其源码实现)。

安装完成后,可以在终端中执行bun --versionspacetime --version确认两个命令均已就绪。

第一步:创建项目 —— 一条命令启动开发环境

在任意空目录中执行以下命令,即可创建包含 SpacetimeDB 模块与 Bun 客户端的新项目:

spacetime dev --template bun-ts

这条命令背后做了一系列事情:

  1. 下载并应用模板:拉取bun-ts模板作为项目骨架(与仓库 templates/bun-ts 内容一致);
  2. 启动本地 SpacetimeDB 服务器:在当前机器上运行一个本地数据库实例(默认ws://localhost:3000);
  3. 发布模块:将spacetimedb/src/index.ts中定义的表与 reducer 编译发布到本地服务器;
  4. 生成 TypeScript 绑定:自动生成客户端用的类型安全绑定代码到src/module_bindings/目录。

这意味着你不需要手动安装数据库、配置连接串或编写任何胶水代码,一条命令就进入可开发状态。

第二步:认识项目结构 —— 服务端与客户端一目了然

spacetime dev生成的项目结构如下:

my-spacetime-app/ ├── spacetimedb/ # 你的 SpacetimeDB 模块(服务端) │ └── src/ │ └── index.ts # 服务端逻辑:表与 reducer 定义 ├── src/ │ ├── main.ts # Bun 客户端脚本 │ └── module_bindings/ # 自动生成的类型绑定(勿手改) └── package.json # 客户端依赖与脚本

各部分职责:

  • spacetimedb/:服务端模块目录。它在仓库模板中是独立子包(见 templates/bun-ts/spacetimedb/package.json),依赖spacetimedb运行时,并提供buildspacetime build)与publishspacetime publish)两个脚本;
  • spacetimedb/src/index.ts:模块入口,定义表结构(Tables)与 reducer 函数,是服务端逻辑的"单一真相";
  • src/main.ts:Bun 客户端入口,负责连接数据库、订阅数据并实现交互式 CLI;
  • src/module_bindings/spacetimeCLI 根据服务端模块自动生成的类型安全绑定。每个表、每个 reducer 都会生成独立的类型文件(如person_table.tsadd_reducer.ts),此目录属于生成产物,切勿手工编辑——文件头部的注释也明确声明了这一点。

第三步:理解表(Tables)与 Reducer —— SpacetimeDB 的核心心智模型

打开spacetimedb/src/index.ts,模板默认提供了一张person表和两个 reducer。仓库中该文件的真实实现为:

import { schema, table, t } from 'spacetimedb/server'; const spacetimedb = schema({ person: table( { public: true }, { name: t.string(), } ), }); export default spacetimedb; export const init = spacetimedb.init(_ctx => { // Called when the module is initially published }); export const onConnect = spacetimedb.clientConnected(_ctx => { // Called every time a new client connects }); export const onDisconnect = spacetimedb.clientDisconnected(_ctx => { // Called every time a client disconnects }); 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!'); });

(完整源码见 templates/bun-ts/spacetimedb/src/index.ts,比文档示例额外包含initonConnectonDisconnect三个生命周期回调钩子。)

两个核心概念需要理解透彻:

  • 表(Tables)存储数据person表声明为{ public: true },表示所有客户端都可以订阅读取。字段name通过类型构建器t.string()声明为字符串类型;
  • Reducer 是唯一的写入口:reducer 是修改数据的函数,客户端无法直接写库,只能调用 reduceraddreducer 接收一个{ name: string }参数并执行ctx.db.person.insert({ name })完成插入;sayHelloreducer 无参数,遍历ctx.db.person.iter()逐条打印问候,最后打印Hello, World!

spacetimedb.reducer()的写法是"先声明参数 schema(作为类型与运行时双重描述),再提供实现函数"。该 schema 会被spacetimeCLI 用于生成客户端的类型安全调用接口(见 templates/bun-ts/src/module_bindings/add_reducer.ts)。

第四步:运行 Bun 客户端 —— 两种启动模式

打开第二个终端,进入项目根目录执行:

# 开发模式:文件变更自动重载 bun run dev # 单次运行 bun run start

两种模式的差异来自 templates/bun-ts/package.json 中的脚本定义:

{ "scripts": { "dev": "bun --watch src/main.ts", "start": "bun src/main.ts", "build": "bun build src/main.ts --outdir dist", "spacetime:generate": "spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb" } }
  • bun run dev等价于bun --watch src/main.ts,利用 Bun 原生 watch 能力,编辑src/main.ts后进程自动重启,适合开发迭代;
  • bun run start直接执行一次;
  • 附加的spacetime:generate脚本可随时手动重新生成绑定(当你修改了服务端模块的表/reducer 后,通过bun run spacetime:generate刷新客户端类型)。

第五步:使用交互式 CLI —— 与模块实时对话

客户端启动后,控制台会依次输出连接信息、身份标识、当前数据快照与可用命令:

Connecting to SpacetimeDB... URI: ws://localhost:3000 Module: bun-ts Connected to SpacetimeDB! Identity: abc123def456... Current people (0): (none yet) Commands: <name> - Add a person with that name list - Show all people hello - Greet everyone (check server logs) Ctrl+C - Quit > Alice > [Added] Alice > Bob > [Added] Bob > list > People in database: - Alice - Bob > hello > Called sayHello reducer (check server logs)

交互逻辑对应的客户端实现(见 templates/bun-ts/src/main.ts 中的setupCLI):

  • 输入任意名称 → 调用conn.reducers.add({ name: text }),触发服务端addreducer;
  • 输入list→ 通过conn.db.person.iter()遍历本地缓存的订阅数据并打印;
  • 输入hello→ 调用conn.reducers.sayHello({}),服务端日志输出问候;
  • Ctrl+C→ 触发SIGINT处理,调用conn.disconnect()优雅断开。

第六步:理解客户端代码 —— DbConnection 与订阅模型

src/main.ts是理解 SpacetimeDB TypeScript 客户端的入口。它基于生成的绑定类DbConnection(其基类与构建器实现在 sdks/typescript/src/sdk/db_connection_impl.ts)完成以下工作:

import { Identity } from 'spacetimedb'; import { DbConnection, ErrorContext, EventContext, } from './module_bindings/index.js'; // Configuration - Bun supports .env files natively const HOST = process.env.SPACETIMEDB_HOST ?? 'ws://localhost:3000'; const DB_NAME = process.env.SPACETIMEDB_DB_NAME ?? 'bun-ts'; async function main(): Promise<void> { console.log(`Connecting to SpacetimeDB...`); console.log(` URI: ${HOST}`); console.log(` Module: ${DB_NAME}`); const token = await loadToken(); // Build and establish connection DbConnection.builder() .withUri(HOST) .withDatabaseName(DB_NAME) .withToken(token) .onConnect(onConnect) .onDisconnect(onDisconnect) .onConnectError(onConnectError) .build(); }

(完整实现见 templates/bun-ts/src/main.ts,比文档示例增加了onDisconnect/onConnectError错误处理与身份截断显示等细节。)

关键 API 及其语义:

  • DbConnection.builder():链式配置连接。.withUri()指定数据库地址(默认ws://localhost:3000),.withDatabaseName()指定模块名(默认bun-ts),.withToken()传入持久化的认证令牌,.onConnect/.onDisconnect/.onConnectError注册三类连接生命周期回调;
  • subscriptionBuilder():构建订阅。.onApplied(ctx => ...)在订阅数据首次落地后回调,.subscribeToAllTables()订阅全部表;回调中的ctxSubscriptionEventContext,可通过ctx.db.person.iter()读取当前数据快照;
  • conn.db.person.onInsert(...):注册表变更回调。任何客户端(包括 CLI)插入person行时,所有已订阅的客户端都会实时收到onInsert事件并打印[Added] ...
  • conn.db即查询构建器:生成的tables对象由__makeQueryBuilder构造,每个表引用同时充当查询构建器(见 templates/bun-ts/src/module_bindings/index.ts)。

与浏览器应用不同,Bun 环境下认证令牌不再依赖localStorage,而是通过Bun.file()Bun.write()持久化到本地文件.spacetimedb-token

// Token persistence using Bun APIs const TOKEN_FILE = '.spacetimedb-token'; async function loadToken(): Promise<string | undefined> { try { const file = Bun.file(TOKEN_FILE); if (await file.exists()) { const text = await file.text(); return text.trim() || undefined; } } catch (err) { console.warn('Could not load token:', err); } return undefined; } async function saveToken(token: string): Promise<void> { try { await Bun.write(TOKEN_FILE, token); } catch (err) { console.warn('Could not save token:', err); } }

首次连接时服务端下发的 token 会被保存;后续启动读取同一 token,即可复用同一身份(Identity),保证数据归属稳定。

第七步:用 SpacetimeDB CLI 验证与调试

除客户端交互外,还可以直接用spacetimeCLI 调用 reducer 和查询数据,且CLI 的改动会实时同步到运行中的 Bun 客户端(这正是订阅机制的效果):

# 调用 add reducer 插入一个人 spacetime call add Charlie # 查询 person 表 spacetime sql "SELECT * FROM person" name --- "Alice" "Bob" "Charlie" # 调用 sayHello 向所有人打招呼 spacetime call say_hello # 查看模块日志 spacetime logs 2025-01-13T12:00:00.000000Z INFO: Hello, Alice! 2025-01-13T12:00:00.000000Z INFO: Hello, Bob! 2025-01-13T12:00:00.000000Z INFO: Hello, Charlie! 2025-01-13T12:00:00.000000Z INFO: Hello, World!

四个命令的用途:

  • spacetime call <reducer> [args...]:远程调用指定 reducer。注意 reducer 在 CLI 中以snake_case命名(say_hello),而 TypeScript 绑定中为 camelCase(sayHello);
  • spacetime sql "...":以 SQL 直接查询数据库,支持SELECT等只读操作;
  • spacetime logs:实时流式查看模块的console.info等日志输出,是调试 reducer 的重要工具。

第八步:Bun 专属特性 —— 为什么这个模板与众不同

该模板特意为 Bun 运行时做了针对性优化,主要有四点:

原生 WebSocket,零额外依赖。Bun 内置WebSocket实现,无需安装undici之类的 polyfill。SpacetimeDB TypeScript SDK 的 WebSocket 解析逻辑(sdks/typescript/src/sdk/ws.ts)会优先检测全局WebSocket——在 Bun(以及浏览器和 Node ≥ 22)环境下直接使用原生实现,仅在缺失时才惰性加载undici兜底,这正是 Bun 下"开箱即用"的底层原因。

内置 TypeScript 运行能力。Bun 直接执行.ts文件,无需tsxts-node等转译工具链,启动更快、依赖更少。bun --watch同时提供开发期热重载。

环境变量自动加载。Bun 原生读取.env文件,模板通过SPACETIMEDB_HOSTSPACETIMEDB_DB_NAME两个环境变量配置连接参数,默认值分别回落到ws://localhost:3000bun-ts。配置方式有两种:

# 方式一:命令行内联环境变量 SPACETIMEDB_HOST=ws://localhost:3000 \ SPACETIMEDB_DB_NAME=my-app \ bun run start # 方式二:创建 .env 文件(Bun 自动加载) echo "SPACETIMEDB_HOST=ws://localhost:3000" > .env echo "SPACETIMEDB_DB_NAME=my-app" >> .env bun run start

原生文件 API 持久化令牌。模板使用Bun.file()Bun.write()读写.spacetimedb-token,相对 Node.js 的fs模块在 Bun 上性能更好、写法更简洁。

下一步学习路径

至此,你已经跑通了 SpacetimeDB + Bun 的完整开发闭环:从spacetime dev --template bun-ts一键创建项目,到编写表与 reducer、连接订阅、交互式 CLI 与spacetimeCLI 双向调试,再到 Bun 专属特性的运用。

如果你想继续深入,推荐以下仓库内资源:

  • Chat App 完整教程:一个完整的聊天应用示例,展示多表、多 reducer 与真实业务场景的工程组织;
  • TypeScript SDK 参考文档:DbConnectionSubscriptionBuilder、reducer 调用与事件上下文的详细 API 说明;
  • 模板源码 templates/bun-ts:本文所有代码的权威来源,可对照阅读src/main.tsspacetimedb/src/index.tssrc/module_bindings/下的生成文件,理解绑定层如何与 SDK 运行时协作。

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 18:55:35

C++物业管理系统代码剖析:面向对象、文件持久化与数据校验

简介&#xff1a;C物业管理系统是一份完整的课程设计与实战项目资源&#xff0c;适合学习C面向对象编程、文件读写、GUI开发及数据库应用的开发者参考。压缩包共99个文件&#xff0c;包含32个cpp源文件、31个头文件、29个ui界面文件&#xff0c;另有sql数据库脚本、Qt工程配置与…

作者头像 李华
网站建设 2026/9/13 18:54:47

小体积高扭矩电机驱动:通用MCU与硅MOS方案的优化和取舍

做电机驱动的朋友应该都碰到过类似的问题&#xff1a;明明方案也是FOC、也是MCU加MOS管&#xff0c;凭什么别人家的板子又小扭矩又大&#xff0c;自己的板子要么很大&#xff0c;要么一猛起就发烫&#xff1f;早几年我折腾无人机电调、电动工具和机器人关节的时候&#xff0c;被…

作者头像 李华
网站建设 2026/9/13 18:54:45

PMSM电机FOC控制全解析:从坐标变换到无感调试

FOC在圈里被吹得神乎其神&#xff0c;但也确实劝退了很多人。早几年我刚开始碰PMSM无感控制的时候&#xff0c;光看那堆坐标变换的公式推导就想摔键盘。后来真正把代码跑起来、把波形调出来&#xff0c;回头看才发现&#xff0c;FOC没有那么玄乎&#xff0c;但也绝不是一个晚上…

作者头像 李华
网站建设 2026/9/13 18:53:29

淘股吧实盘交易策略与市场分析

1. 淘股吧实盘交易概述淘股吧作为国内知名的股票投资交流社区&#xff0c;其"实盘"功能一直是投资者展示交易成果、交流投资心得的重要平台。2025年5月的实盘数据反映了当前市场环境下投资者的操作策略与收益情况&#xff0c;具有以下典型特征&#xff1a;行业分布集…

作者头像 李华
网站建设 2026/9/13 18:53:02

Axolotl 大模型微调实战教程:4条命令跑通首次训练

Axolotl 大模型微调实战教程&#xff1a;4条命令跑通首次训练 【免费下载链接】axolotl Go ahead and axolotl questions 项目地址: https://gitcode.com/GitHub_Trending/ax/axolotl Axolotl 是一个开源 LLM 微调框架&#xff0c;用一份 YAML 配置文件即可控制数据加载…

作者头像 李华