SpacetimeDB Angular 快速入门:用 `spacetime dev --template angular-ts` 在 5 分钟内跑通前后端

发布时间:2026/9/12 14:08:44
SpacetimeDB Angular 快速入门:用 `spacetime dev --template angular-ts` 在 5 分钟内跑通前后端
SpacetimeDB Angular 快速入门用spacetime dev --template angular-ts在 5 分钟内跑通前后端【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB本篇指南以 SpacetimeDB 官方 Angular 快速入门文档为骨架结合当前仓库中的angular-ts模板源码带你从零搭建一个「SpacetimeDB 服务端模块 Angular 前端」的全栈应用。读完你将掌握如何用一条命令完成本地服务器启动、模块发布、TypeScript 绑定生成与 Angular 开发服务器启动如何编写表table与 reducerreducer如何用 SpacetimeDB CLI 直接调用 reducer、执行 SQL 查询和查看模块日志以及模板中 Angular 连接层injectSpacetimeDB、injectTable、injectReducer的底层实现原理。环境准备开始前需要确保本机满足以下两个前提条件Node.js 18Angular 应用构建与运行所需运行时环境SpacetimeDB CLI提供spacetime dev、spacetime publish、spacetime call、spacetime sql、spacetime logs等核心命令负责初始化模板、发布模块并与本地/云端数据库交互。两个条件满足后即可进入下一步创建项目。创建项目一条命令完成全链路启动在任意空目录中执行spacetime dev --template angular-ts这条命令会替你依次完成四件事启动本地 SpacetimeDB 服务器发布你的模块把spacetimedb/目录下的服务端代码编译并发布到本地服务器生成 TypeScript 绑定生成到src/module_bindings/目录启动 Angular 开发服务器ng serve默认端口 4200。从 CLI 源码看--template参数由 crates/cli/src/subcommands/dev.rs 解析它支持「模板 ID 或 GitHub 仓库owner/repo或 URL」两种形式模板 ID 即本项目中的angular-ts。同时该文件注释明确要求所有服务端模板的代码必须放在spacetimedb/目录下这正是模板目录结构如此设计的原因。注意如果当前目录已经存在 SpacetimeDB 项目--template会被忽略CLI 会打印Warning: --template option is ignored because a SpacetimeDB project already exists.因此该命令应在全新目录中执行。也可以手动初始化如果你想更精细地控制初始化过程也可以使用spacetime init命令手动选择模板spacetime init --template angular-ts初始化完成后再分别执行模块发布与前端启动spacetime publish --module-path spacetimedb --server local npm install npm run dev模板的 package.json 中预设了这些常用脚本dev运行node scripts/dev.mjs先为前端生成本地环境配置再启动ng servebuildng build生产构建spacetime:publish:local发布到本地服务器--server localspacetime:publish发布到主云服务器--server maincloudspacetime:generate用 CLI 重新生成 TypeScript 绑定spacetime generate --lang typescript。打开应用开发服务器启动后浏览器访问http://localhost:4200即可看到运行中的应用。页面会显示连接状态Connected / Disconnected绿色/红色一个输入框和「Add Person」按钮一个「People」列表实时展示person表中的所有行。模板自带了一个已连接到 SpacetimeDB 的基础 Angular 应用你可以在页面上直接添加名字并实时看到列表更新——这一切的背后是订阅机制在起作用详见下文「Angular 前端如何与数据库联动」。项目结构解析模板初始化后你的项目以my-spacetime-app/为例包含服务端与客户端两部分代码my-spacetime-app/ ├── spacetimedb/ # 你的 SpacetimeDB 模块 │ └── src/ │ └── index.ts # 服务端逻辑表与 reducer 定义 ├── src/ # Angular 前端 │ └── app/ │ ├── app.component.ts │ ├── app.config.ts │ └── module_bindings/ # 自动生成的类型 ├── angular.json └── package.json对照当前仓库中的真实模板templates/angular-ts完整的目录还要更丰富一些spacetimedb/src/index.ts服务端模块入口定义表与 reducer下文详述src/app/app.component.tsAngular 根组件负责 UI 渲染与 reducer 调用src/app/app.config.ts应用级配置通过provideSpacetimeDB注入数据库连接src/environments/environment.ts默认连接配置主机与数据库名src/module_bindings/自动生成的绑定层包含tables、reducers、DbConnection、SubscriptionBuilder等类型化 APIscripts/dev.mjs开发脚本负责生成本地环境变量文件angular.json、package.json、tsconfig*.jsonAngular 工程配置。一个值得注意的细节src/module_bindings/下的文件是自动生成的每个文件头部都有一行显式声明——THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.此文件由 SpacetimeDB 自动生成对它的修改不会被保存请直接修改模块源码。这意味着你不要手工编辑绑定文件改表结构/ reducer 签名时只需修改spacetimedb/src/index.ts然后重新生成绑定即可。前后端各自的编辑入口服务端编辑spacetimedb/src/index.ts添加表tables和 reducer客户端编辑src/app/app.component.ts构建你的 UI。理解表table与 reducerreducer打开spacetimedb/src/index.ts可以看到模块的核心代码与仓库中 templates/angular-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 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!); });表存储数据的地方schema({...})定义模块的数据库模式。模板中定义了一张person表table({ public: true }, {...})第一个参数是表配置public: true表示该表对客户端公开客户端可以订阅并读取第二个参数是列定义name: t.string()声明了一列字符串类型的name。表负责存储数据是数据库的基本容器。reducer唯一的数据写入方式spacetimedb.reducer(...)定义 reducer——一种服务端函数。Reducer 是修改数据的唯一方式客户端不能直接写表只能通过调用 reducer 间接写入。模板提供了两个 reduceradd接收一个name参数向person表插入一行。参数通过{ name: t.string() }进行类型声明函数体内通过ctx.db.person.insert({ name })执行插入sayHello遍历person表中的每一行用console.info打印问候语。ctx.db.person.iter()返回迭代器逐行访问所有数据。此外模板还展示了三个生命周期钩子这在原文档中未展开但仓库源码中确实存在spacetimedb.init(_ctx {...})模块首次发布时调用spacetimedb.clientConnected(_ctx {...})每次有新客户端连接时调用spacetimedb.clientDisconnected(_ctx {...})每次有客户端断开时调用。你可以在这些钩子里编写初始化数据、在线状态广播等逻辑。用 CLI 测试调用 reducer、查询与看日志打开一个新的终端进入项目目录用 SpacetimeDB CLI 直接与本地数据库交互cd my-spacetime-app # 调用 add reducer插入一个名叫 Alice 的人 spacetime call add Alice # 查询 person 表 spacetime sql SELECT * FROM person name --------- Alice # 调用 sayHello向所有人打招呼 spacetime call say_hello # 查看模块日志 spacetime logs 2025-01-13T12:00:00.000000Z INFO: Hello, Alice! 2025-01-13T12:00:00.000000Z INFO: Hello, World!四个命令逐一说明命令作用spacetime call add Alice调用 reducer。位置参数按 reducer 声明顺序传入Alice即name的值注意 reducer 名sayHello在 CLI 中写作蛇形命名say_hellospacetime sql SELECT * FROM person用标准 SQL 查询表数据spacetime call say_hello调用无参 reducer触发遍历与日志输出spacetime logs实时查看模块的console.info日志输出这一轮操作完整验证了「写入 → 查询 → 计算 → 观测」的全链路数据通过add写入通过 SQL 读到通过sayHello遍历并打日志最终在logs中确认结果。Angular 前端如何与数据库联动模板的核心价值在于Angular 前端与 SpacetimeDB 的连接层已经帮你写好了。打开 templates/angular-ts/src/app/app.config.ts可以看到应用通过 Angular 依赖注入配置数据库连接import { ApplicationConfig, provideBrowserGlobalErrorListeners, } from angular/core; import { provideSpacetimeDB } from spacetimedb/angular; import { DbConnection, ErrorContext } from ../module_bindings; import { Identity } from spacetimedb; import { environment } from ../environments/environment; const HOST environment.SPACETIMEDB_HOST; const DB_NAME environment.SPACETIMEDB_DB_NAME; const onConnect (_conn: DbConnection, identity: Identity, token: string) { localStorage.setItem(auth_token, token); console.log( Connected to SpacetimeDB with identity:, identity.toHexString() ); }; const onDisconnect () { console.log(Disconnected from SpacetimeDB); }; const onConnectError (_ctx: ErrorContext, err: Error) { console.log(Error connecting to SpacetimeDB:, err); }; export const appConfig: ApplicationConfig { providers: [ provideBrowserGlobalErrorListeners(), provideSpacetimeDB( DbConnection.builder() .withUri(HOST) .withDatabaseName(DB_NAME) .withToken(localStorage.getItem(auth_token) || undefined) .onConnect(onConnect) .onDisconnect(onDisconnect) .onConnectError(onConnectError) ), ], };关键点解读provideSpacetimeDB(...)来自spacetimedb/angular包把连接注册为全局 providerDbConnection.builder()来自自动生成的绑定templates/angular-ts/src/module_bindings/index.ts是带模块类型信息的连接构建器.withUri(HOST).withDatabaseName(DB_NAME)指定服务器地址与数据库名.withToken(...)从localStorage读取auth_token实现会话恢复——首次连接成功后 token 会被存到localStorage见onConnect刷新页面后无需重新认证onConnect/onDisconnect/onConnectError连接生命周期回调分别处理连接成功、断开与失败。根组件响应式订阅与 reducer 调用再看 templates/angular-ts/src/app/app.component.tsUI 逻辑非常简洁完全建立在 Angular 的响应式注入之上import { Component } from angular/core; import { injectSpacetimeDB, injectTable, injectReducer, } from spacetimedb/angular; import { tables, reducers } from ../module_bindings; Component({ selector: app-root, template: ..., }) export class App { protected conn injectSpacetimeDB(); protected people injectTable(tables.person); private addReducer injectReducer(reducers.add); protected name ; addPerson(event: Event) { event.preventDefault(); if (!this.name.trim() || !this.conn().isActive) return; // Call the add reducer this.addReducer({ name: this.name }); this.name ; } }三个注入函数各司其职injectSpacetimeDB()返回连接状态信号signalconn().isActive表示当前是否已连接UI 据此显示绿/红状态并禁用输入框与按钮injectTable(tables.person)订阅person表的变更返回响应式查询结果people().rows.length和people().rows在模板中直接渲染当表数据变化时页面会自动更新——这正是 SpacetimeDB 订阅机制带来的实时能力injectReducer(reducers.add)返回一个可调用的 reducer 函数this.addReducer({ name: this.name })即向服务端发起一次 reducer 调用。自动生成的绑定层做了什么在 templates/angular-ts/src/module_bindings/index.ts 中可以看到绑定的完整面貌它从spacetimedb包导入底层运行时再基于模块 schema 生成tablesSchema、reducersSchema、proceduresSchema最终导出tables表引用集合兼作查询构建器query builderreducersreducer 访问器映射DbConnection/DbConnectionBuilder带模块类型信息的连接 APISubscriptionBuilder订阅构建器一系列类型定义EventContext、ReducerEventContext、ErrorContext等。比如person表的行类型由 templates/angular-ts/src/module_bindings/person_table.ts 生成export default __t.row({ name: __t.string(), });而addreducer 的参数类型由 templates/angular-ts/src/module_bindings/add_reducer.ts 生成export default { name: __t.string(), };这些文件是类型安全的关键前端调用 reducer、读取表数据时都有完整的 TypeScript 类型推导编译期即可捕获字段拼写错误与类型不匹配。本地环境配置与scripts/dev.mjs的运行机制Angular 的 esbuild 构建器不会像 Vite 那样自动读取.env文件因此模板用 templates/angular-ts/scripts/dev.mjs 做了一个巧妙的桥接解析.env.local如果存在与process.env按优先级解析两个关键变量SPACETIMEDB_DB_NAME数据库名和SPACETIMEDB_HOST服务器地址——优先取spacetime dev注入的process.env其次取.env.local中的VITE_SPACETIMEDB_DB_NAME/VITE_SPACETIMEDB_HOST最后回退到 templates/angular-ts/src/environments/environment.ts 中的默认值https://maincloud.spacetimedb.com与angular-ts生成src/environments/environment.local.ts通过 angular.json 中的fileReplacements配置在 development 构建时用environment.local.ts替换默认的environment.ts最后以npx ng serve启动 Angular 开发服务器。默认配置中SPACETIMEDB_HOST指向https://maincloud.spacetimedb.com主云服务器而当你使用spacetime dev时CLI 会注入本地服务器地址连接目标自动切换为本地。手动执行npm run dev而不设置环境变量时应用则会尝试连接主云服务器。下一步进阶阅读 TypeScript SDK 参考文档掌握spacetimedb包的完整 API查询构建器、订阅、事务与错误处理等尝试在spacetimedb/src/index.ts中添加新表如message、新 reducer如sendMessage然后重新运行spacetime generate或spacetime dev自动刷新绑定将person表改为非公开public: false观察前端订阅行为的变化理解表可见性与权限控制参考仓库中的其他 Angular 系模板如 templates/react-ts、templates/nextjs-ts对比不同框架接入 SpacetimeDB 的异同。【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考