资讯动态

SpacetimeDB Node.js 快速入门:用 `spacetime dev` 在 5 分钟内跑通实时数据库应用

发布时间:2026/9/13 1:08:29 来源:尧图企业网站定制
SpacetimeDB Node.js 快速入门用spacetime dev在 5 分钟内跑通实时数据库应用【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB本篇指南完整讲解 SpacetimeDB 的 Node.js 快速入门流程使用spacetime dev --template nodejs-ts一条命令创建「TypeScript 模块 Node.js 客户端」的双端项目并深入解读表Table、Reducer、订阅与身份令牌等核心概念。读完本文你将掌握如何运行本地 SpacetimeDB、用 CLI 调用 Reducer 与执行 SQL、编写基于DbConnection的 Node.js 实时客户端并能对照本仓库 nodejs-ts 模板 的真实源码理解其底层原理。原始快速入门文档位于 docs/docs/00100-intro/00200-quickstarts/00300-nodejs.md。前置条件开始之前请确保本地环境满足以下两个要求Node.js 18本文所有命令均在 Node.js 18 及以上版本验证。Node.js 22 拥有原生 WebSocket 支持Node.js 18~21 则由 SDK 自动回退使用undici包模板已将其列入devDependencies见 templates/nodejs-ts/package.json。SpacetimeDB CLI提供spacetime命令行工具用于创建项目、启动本地服务端、发布模块、调用 Reducer 与查询数据。创建项目一条命令启动全栈开发环境在空目录下执行spacetime dev --template nodejs-tsspacetime dev是 SpacetimeDB 的「开发者模式」命令它会自动完成以下四件事启动本地 SpacetimeDB 服务端默认监听ws://localhost:3000构建并发布你的模块module把服务端逻辑部署到本地数据库生成 TypeScript 类型绑定module bindings让客户端代码获得与服务端 schema 完全一致的强类型运行 Node.js 客户端实时连接并展示数据变化。也就是说从零到跑通一个包含服务端与客户端的最小可运行应用只需要这一条命令。仓库中与nodejs-ts同类的模板还包括react-ts、bun-ts、deno-ts、basic-ts等参见 templates 目录你可以在spacetime dev --template 名称中自由切换。探索项目结构服务端与客户端一目了然项目创建完成后你会得到类似下面的目录结构my-spacetime-app/ ├── spacetimedb/ # 你的 SpacetimeDB 模块 │ └── src/ │ └── index.ts # 服务端逻辑表与 Reducer ├── src/ │ ├── main.ts # Node.js 客户端脚本 │ └── module_bindings/ # 自动生成的类型绑定 └── package.json对照仓库中的真实模板 templates/nodejs-ts结构还可以展开得更细templates/nodejs-ts/ ├── spacetimedb/ # 服务端模块 │ ├── src/index.ts # 定义 schema、表与 Reducer │ ├── package.json # 模块的 build / publish 脚本 │ └── tsconfig.json ├── src/ # Node.js 客户端 │ ├── main.ts # 连接、订阅、事件回调 │ └── module_bindings/ # 自动生成切勿手改 │ ├── index.ts # DbConnection / 订阅构建器等 │ ├── person_table.ts # person 表的行类型 │ ├── add_reducer.ts # add Reducer 参数类型 │ ├── say_hello_reducer.ts # say_hello Reducer 参数类型 │ └── types/ ├── package.json # 客户端依赖与脚本 └── tsconfig.json职责划分非常清晰spacetimedb/src/index.ts—— 服务端逻辑编辑它来添加表Table和 Reducersrc/main.ts—— Node.js 客户端编辑它来构建你的应用交互src/module_bindings/—— 由 CLI 自动生成的类型绑定文件头明确声明「自动生成、编辑不会被保存」任何修改都应回到模块源码spacetimedb/src/index.ts再重新生成。理解表与 Reducer服务端模块的核心打开spacetimedb/src/index.ts仓库对应文件为 templates/nodejs-ts/spacetimedb/src/index.ts模板内置了一张person表和两个 Reduceradd插入一个人与sayHello向所有人问好。定义表Tableimport { schema, table, t } from spacetimedb/server; const spacetimedb schema({ person: table( { public: true }, { name: t.string(), } ), }); export default spacetimedb;table(options, columns)声明一张表。{ public: true }表示该表对客户端公开可订阅第二个参数是列定义这里只有一列name类型为t.string()。schema({ ... })把多张表聚合为一个模块 schemaexport default后由 CLI 读取生成客户端绑定。类型构造器t支持字符串、整数、浮点数、布尔、数组、对象等 SATS 类型可用于后续扩展更复杂的表结构。定义 ReducerReducerexport 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!); });Reducer 是写入数据库的唯一途径。客户端无法直接改表只能通过spacetime call或 SDK 调用 Reducer 来增删改数据表本身存储数据Reducer 负责修改数据。add接收{ name: t.string() }参数在ctx.db.person.insert(...)中完成插入sayHello不接收参数通过ctx.db.person.iter()遍历当前所有行用console.info输出问候日志——这些日志会出现在服务端日志中可用spacetime logs查看。模板的完整源码中还额外定义了生命周期钩子它们是理解服务端行为的补充素材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 });从源码结构可以看出模块发布、客户端连接、客户端断开三个时机分别对应init、clientConnected、clientDisconnected三个注册入口适合在正式应用中初始化种子数据、统计在线人数或做清理工作。运行客户端再次执行spacetime dev --template nodejs-tsspacetime dev会同时启动服务端与 Node.js 客户端。客户端连接成功后订阅所有表并实时打印人员列表的增删变化。按CtrlC即可退出。如果你想手动分开控制服务端与客户端模板根目录 package.json 还提供了以下脚本可作为参考{ scripts: { dev: esbuild src/main.ts --bundle --platformnode --outfiledist/main.js --formatesm node dist/main.js, start: node dist/main.js, build: esbuild src/main.ts --bundle --platformnode --outfiledist/main.js --formatesm, typecheck: tsc --noEmit, spacetime:generate: spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb } }其中spacetime:generate对应绑定生成命令spacetime generate --lang typescript --out-dir src/module_bindings --module-path spacetimedb修改模块源码后重新生成客户端类型即可。用 SpacetimeDB CLI 调用 Reducer 与查询数据服务端跑起来后打开另一个终端用 CLI 与数据库交互所有变更都会实时反映到正在运行的 Node.js 客户端中# 添加两个人 spacetime call add Alice spacetime call add Bob # 向所有人问好结果查看服务端日志 spacetime call say_hello # 查询数据库 spacetime sql SELECT * FROM personspacetime call reducer [args...]调用模块中定义的 Reducer。CLI 会把Alice这类位置参数按 Reducer 签名解析并序列化spacetime sql query以 SQL 方式直接查询表数据。更多 CLI 示例与完整输出# 调用 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!注意 CLI 中的 Reducer 名使用下划线风格say_hello而模块源码中为驼峰风格sayHello表名、列名在生成绑定与 SQL 查询时也遵循统一的命名转换规则。spacetime logs展示的正是sayHello中console.info写入的服务端日志。深入理解客户端代码DbConnection、订阅与令牌打开src/main.ts仓库对应文件为 templates/nodejs-ts/src/main.ts这是完整的 Node.js 客户端。它通过DbConnection.builder()连接 SpacetimeDB订阅表并注册插入/删除回调。与浏览器端应用不同Node.js 客户端把认证令牌保存在文件中而不是localStorage里。建立连接import { Identity } from spacetimedb; import { DbConnection } from ./module_bindings/index.js; const HOST process.env.SPACETIMEDB_HOST ?? ws://localhost:3000; const DB_NAME process.env.SPACETIMEDB_DB_NAME ?? nodejs-ts; DbConnection.builder() .withUri(HOST) .withDatabaseName(DB_NAME) .withToken(loadToken()) // 从文件加载已保存的令牌 .onConnect(onConnect) .onDisconnect(onDisconnect) .onConnectError(onConnectError) .build();withUri(uri)指定服务端地址默认ws://localhost:3000withDatabaseName(name)指定要连接的模块/数据库名withToken(token)携带身份令牌。首次连接时未保存令牌可传undefined服务端会在onConnect回调中下发新的身份与令牌onConnect / onDisconnect / onConnectError分别处理连接成功、断开可选错误信息与连接失败模板中失败时直接process.exit(1)。DbConnection与SubscriptionBuilder等类型均来自自动生成的 src/module_bindings/index.ts它把服务端 schema 编译为强类型的客户端 API——表引用同时可用作查询构建器Reducer 也被转换为可直接调用的访问器。连接成功后的订阅与事件回调function onConnect(conn: DbConnection, identity: Identity, token: string): void { console.log(\nConnected to SpacetimeDB!); console.log(Identity: ${identity.toHexString().slice(0, 16)}...); saveToken(token); // 保存令牌供下次连接使用 // 订阅所有表 conn .subscriptionBuilder() .onApplied(ctx { const people [...ctx.db.person.iter()]; console.log(\nCurrent people (${people.length}):); // ...逐行打印 }) .onError((_ctx, err) console.error(Subscription error:, err)) .subscribeToAllTables(); // 监听表变化 conn.db.person.onInsert((_ctx, person) { console.log([Added] ${person.name}); }); conn.db.person.onDelete((_ctx, person) { console.log([Removed] ${person.name}); }); }订阅SubscriptionsubscriptionBuilder().subscribeToAllTables()订阅所有表onApplied回调在订阅快照首次应用时触发可读取当前全量数据。订阅是实时更新的前提——服务端把变更集推送给客户端。事件回调conn.db.person.onInsert(...)与onDelete(...)注册行级回调客户端即可在人员新增/删除的瞬间收到通知并打印。身份与令牌identity.toHexString()输出身份标识saveToken(token)把令牌持久化到本地文件。Node.js 特有的令牌文件持久化由于 Node.js 没有浏览器环境的localStorage模板用fs模块实现了基于文件的令牌存取const TOKEN_FILE path.join(__dirname, .., .spacetimedb-token); function loadToken(): string | undefined { try { if (fs.existsSync(TOKEN_FILE)) { return fs.readFileSync(TOKEN_FILE, utf-8).trim(); } } catch (err) { console.warn(Could not load token:, err); } return undefined; } function saveToken(token: string): void { try { fs.writeFileSync(TOKEN_FILE, token, utf-8); } catch (err) { console.warn(Could not save token:, err); } }令牌文件位于项目根目录下的.spacetimedb-token。首次连接时文件不存在loadToken()返回undefined连接成功后saveToken()将其落盘之后每次重启客户端都会复用该身份实现身份持久化。自动生成的类型绑定服务端 schema 修改后CLI 会重新生成 module_bindings 下的类型文件。例如 person_table.ts 定义了person表的行类型export default __t.row({ name: __t.string(), });add_reducer.ts 定义了addReducer 的参数 schemasay_hello_reducer.ts 定义了无参 Reducer。客户端代码因此获得了端到端的类型安全表结构与 Reducer 签名一旦在服务端改动绑定会同步更新编译期即可发现调用不匹配。Node.js 环境注意事项WebSocket 支持Node.js 22原生支持 WebSocket直接使用内置实现Node.js 18~21SDK 自动使用undici包提供的 WebSocketundici已包含在模板的devDependencies中无需手动安装。通过环境变量配置连接模板默认从环境变量读取连接参数未设置时回退到默认值# 通过环境变量配置 SPACETIMEDB_HOSTws://localhost:3000 \ SPACETIMEDB_DB_NAMEmy-app \ npm run start # 或者使用 .env 文件配合 dotenv对应源码位于 templates/nodejs-ts/src/main.ts 顶部const HOST process.env.SPACETIMEDB_HOST ?? ws://localhost:3000; const DB_NAME process.env.SPACETIMEDB_DB_NAME ?? nodejs-ts;退出方式按CtrlC停止客户端连接失败时模板会打印错误并调用process.exit(1)。下一步参考 Chat App 教程跟随一个完整的聊天应用示例把表、Reducer、订阅与多客户端交互串起来阅读 TypeScript SDK Reference核心概念 → 客户端 → TypeScript 参考获取DbConnection、订阅构建器等 API 的详细文档如需查看模板自身的说明可直接阅读 templates/nodejs-ts/README.md其内容与本篇指南一一对应。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价